【JAVA应用】Lambda表达式
JDK8新特性
- Lambda表达式和@FunctionnalInterface注解
- Stream类
- 移除PermGen空间,加入Metaspace
- Optional
- 时间工具类
- 反射获取class的方法能获取到真实的参数名了,之前只能获取到编译后的变量,是一个替换的变量
Lambda
优点
- 函数式编程是编程语言的发展方向,而java要顺应这个趋势,而lambda又是函数式编程的基础内容,所以现在好处一是顺应了编程语言的发展趋势
- 代码简洁,可读性变高了
- 改善了集合的操作,map,reduce,filter提供了并行化
- 对递归做了一定的优化递归优化,尾递归优化一般操作中我们不会关注到,如果你用Lambda,他会自己编译帮你实现
缺点
- 调式麻烦
- 新的方式,有学习成本
- 类型不明确,转换不方便
- 并行计算需要预热,而且只对Collection支持的比较好,其他类型支持一般,没有并行计算的话一般情况下比for循环要慢
jdk8中Stream比你用for循环慢5倍
- for循环毕竟一直存在的,JIT已经对他进行了长时间的优化
- for循环对缓存是友好的,而Stream则还没有做到这一点,所以如果是int基本类型的话,差距会打,但是如果是引用类型Integer的话差距就不大了
- 但是如果你用CPU密集型的操作的话,如果用到了Stream的并行计算,那么差距就会变小了
形成上面的根本原因是
Lambda的实现方式
Lambda实现
Lambda其实就是生成了私有方法,内容就是你在大括号中定义的,最后替换而已,如果你定义了一样的话他会在运行期报错,这个我觉得应该在编译器就报错的,或者编译器替换成一个不一样的
stream应用
public static void main(String[] args) {
String[] strings = new String[]{"a","bbb","cc","bbb"};
System.out.println("\n1. allMatch: 是否所有断言都通过,Predicate:就是定义的一个断言类");
System.out.println(Arrays.stream(strings).allMatch(x -> x.startsWith("a")));
System.out.println("\n2. anyMatch: 任何一个匹配都通过");
System.out.println(Arrays.stream(strings).anyMatch(x -> x.startsWith("a")));
System.out.println("\n3. forEach: 并行遍历,输出顺序可能和定义的不一致");
Arrays.stream(strings).forEach(x -> System.out.printf("%s\t", x));
System.out.println("\n\n4. forEachOrdered: 顺序遍历,输出顺序和定义的一致");
Arrays.stream(strings).forEachOrdered(x -> System.out.printf("%s\t", x));
System.out.println("\n\n5 collect: 对流进行收集,传入一个收集器Collector,可以使用Collectors提供的方法");
System.out.println(Arrays.stream(strings).collect(Collectors.joining(",")));
System.out.println("\n6 noneMatch: 任何一个都不匹配成功才返回true");
System.out.println(Arrays.stream(strings).noneMatch(x -> x.startsWith("b")));
System.out.println("\n7 count: 总数");
System.out.println(Arrays.stream(strings).count());
System.out.println("\n8 distinct: 返回去重以后的stream");
Arrays.stream(strings).distinct().forEach(x -> System.out.printf("%s\t",x));
System.out.println("\n\n9. filter: 过滤");
Arrays.stream(strings).filter(x -> x.startsWith("a")).forEach(x -> System.out.println(x));
System.out.println("\n10. findAny: 只要有任意一个数据就可以返回,返回的是Optional");
System.out.println(Arrays.stream(strings).findAny().get());
System.out.println("\n11. findFirst: 返回第一个,返回的是Optional");
System.out.println(Arrays.stream(strings).findFirst().get());
System.out.println("\n12. limit: 截取前几个");
Arrays.stream(strings).limit(2).forEach(x -> System.out.printf("%s\t",x));
System.out.println("\n\n13. max: 通过Comparator方法进行排序,返回最大值");
System.out.println(Arrays.stream(strings).max((x, y) -> x.compareTo(y)).get());
System.out.println("\n\n14. min: 通过Comparator方法进行排序,返回最小值");
System.out.println(Arrays.stream(strings).min((x, y) -> x.compareTo(y)).get());
System.out.println("\n15. peek: peek是瞥一眼的意思,这里简单理解就是只能看一下但是不能动," +
"和map的区别是即便操作了数据返回的stream也不受影响" +
"和forEach的区别是peek返回的还是流,而forEach没有返回值");
Arrays.stream(strings).peek(x -> x.substring(0,1)).forEach(x -> System.out.printf("%s\t", x));
System.out.println("\n\n16. skip: 跳过指定位置的数据");
Arrays.stream(strings).skip(1).forEach(x -> System.out.printf("%s\t", x));
System.out.println("\n\n17. sorted: 默认按升序排序,可以自定义排序");
Arrays.stream(strings).sorted().forEach(x -> System.out.printf("%s\t", x));
System.out.println("\n\n18. toArray: 不指定返回类型,默认返回Object");
for (Object o : Arrays.stream(strings).toArray()) {
System.out.printf("%s\t", o);
}
System.out.println("\n\n19. toArray: 指定返回类型");
for (String s : Arrays.stream(strings).toArray(String[]::new)) {
System.out.printf("%s\t", s);
}
System.out.println("\n\n20. map: 遍历操作");
Arrays.stream(strings).map(x -> System.out.printf("%s\t",x));
String[][] strings1 = new String[][]{{"a","b","c"},{"e","f","g"}};
System.out.println("\n\n21. flatMap: flat是扁平的意思,flatMap可以用来把二维数据拉平到一维的");
Arrays.stream(strings1).flatMap(x -> Arrays.stream(x)).forEach(x -> System.out.printf("%s\t",x));
System.out.println("\n\n22. flatMapToInt: 要求遍历的是IntStream");
Arrays.stream(strings).flatMapToInt(x -> IntStream.of(x.length())).forEach(x -> System.out.printf("%s\t",x));
System.out.println("\n\n23. reduce: 聚合操作");
System.out.println(Arrays.stream(strings).reduce((x,y) -> x+y).get());
}