Lambda表达式可以看成是匿名类一点点演变过来
1. 匿名类的正常写法
HeroChecker c1 = new HeroChecker() {
public boolean test(Hero h) {
return (h.hp>100 && h.damage<50);
}
};
2. 把外面的壳子去掉
只保留方法参数和方法体
参数和方法体之间加上符号 ->
HeroChecker c2 = (Hero h) ->{
return h.hp>100 && h.damage<50;
};
3. 把return和{}去掉
HeroChecker c3 = (Hero h) ->h.hp>100 && h.damage<50;
4. 把 参数类型和圆括号去掉(只有一个参数的时候,才可以去掉圆括号)
HeroChecker c4 = h ->h.hp>100 && h.damage<50;
5. 把c4作为参数传递进去
filter(heros,c4);
6. 直接把表达式传递进去
filter(heros, h -> h.hp > 100 && h.damage < 50);
Lambda比较适合用在简短的业务代码中,并不适合用在复杂的系统中,会加大维护成本。
二、引用静态方法
首先为TestLambda添加一个静态方法:
Lambda表达式:
在Lambda表达式中调用这个静态方法:
调用静态方法还可以改写为:
public static boolean testHero(Hero h) {
return h.hp>100 && h.damage<50;
}
Lambda表达式:
filter(heros, h->h.hp>100 && h.damage<50);
在Lambda表达式中调用这个静态方法:
filter(heros, h -> TestLambda.testHero(h) );
调用静态方法还可以改写为:
filter(heros, TestLambda::testHero);
二、引用对象方法
TestLambda testLambda = new TestLambda();
filter(heros, testLambda::testHero);
三、引用构造方法
有的接口中的方法会返回一个对象,比如java.util.function.Supplier提供
了一个get方法,返回一个对象。
设计一个方法,参数是这个接口
为了调用这个方法,有3种方式
第一种匿名类:
第二种:Lambda表达式
第三种:引用构造器
了一个get方法,返回一个对象。
public interface Supplier<T> {
T get();
}
设计一个方法,参数是这个接口
public static List getList(Supplier<List> s){
return s.get();
}
为了调用这个方法,有3种方式
第一种匿名类:
Supplier<List> s = new Supplier<List>() {
public List get() {
return new ArrayList();
}
};
List list1 = getList(s);
第二种:Lambda表达式
List list2 = getList(()->new ArrayList());
第三种:引用构造器
List list3 = getList(ArrayList::new);
四、聚合操作
要了解聚合操作,首先要建立Stream和管道的概念
Stream 和Collection结构化的数据不一样,Stream是一系列的元素,就像是生产线上的罐头一样,一串串的出来。
管道指的是一系列的聚合操作。
管道又分3个部分
管道源:在这个例子里,源是一个List
中间操作: 每个中间操作,又会返回一个Stream,比如.filter()又返回一个Stream, 中间操作是“懒”操作,并不会真正进行遍历。
结束操作:当这个操作执行后,流就被使用“光”了,无法再被操作。所以这必定是流的最后一个操作。 结束操作不会返回Stream,但是会返回int、float、String、 Collection或者像forEach,什么都不返回, 结束操作才进行真正的遍历行为,在遍历的时候,才会去进行中间操作的相关判断
Stream 和Collection结构化的数据不一样,Stream是一系列的元素,就像是生产线上的罐头一样,一串串的出来。
管道指的是一系列的聚合操作。
管道又分3个部分
管道源:在这个例子里,源是一个List
中间操作: 每个中间操作,又会返回一个Stream,比如.filter()又返回一个Stream, 中间操作是“懒”操作,并不会真正进行遍历。
结束操作:当这个操作执行后,流就被使用“光”了,无法再被操作。所以这必定是流的最后一个操作。 结束操作不会返回Stream,但是会返回int、float、String、 Collection或者像forEach,什么都不返回, 结束操作才进行真正的遍历行为,在遍历的时候,才会去进行中间操作的相关判断
每个中间操作,又会返回一个Stream,比如.filter()又返回一个Stream, 中间操作是“懒”操作,并不会真正进行遍历。
中间操作比较多,主要分两类
对元素进行筛选 和 转换为其他形式的流
对元素进行筛选:
filter 匹配
distinct 去除重复(根据equals判断)
sorted 自然排序
sorted(Comparator<T>) 指定排序
limit 保留
skip 忽略
转换为其他形式的流
mapToDouble 转换为double的流
map 转换为任意类型的流
中间操作比较多,主要分两类
对元素进行筛选 和 转换为其他形式的流
对元素进行筛选:
filter 匹配
distinct 去除重复(根据equals判断)
sorted 自然排序
sorted(Comparator<T>) 指定排序
limit 保留
skip 忽略
转换为其他形式的流
mapToDouble 转换为double的流
map 转换为任意类型的流
当进行结束操作后,流就被使用“光”了,无法再被操作。所以这必定是流的最后一个操作。 结束操作不会返回Stream,但是会返回int、float、String、 Collection或者像forEach,什么都不返回,。
结束操作才真正进行遍历行为,前面的中间操作也在这个时候,才真正的执行。
常见结束操作如下:
forEach() 遍历每个元素
toArray() 转换为数组
min(Comparator<T>) 取最小的元素
max(Comparator<T>) 取最大的元素
count() 总数
findFirst() 第一个元素
结束操作才真正进行遍历行为,前面的中间操作也在这个时候,才真正的执行。
常见结束操作如下:
forEach() 遍历每个元素
toArray() 转换为数组
min(Comparator<T>) 取最小的元素
max(Comparator<T>) 取最大的元素
count() 总数
findFirst() 第一个元素