Lambda表达式
一:优化性能
先看一段常见的程序
这段程序很简单,但是,会造成性能上的浪费。你看啊,这里调用showLog函数,直接传递1以及mess1和mess2拼接好的字符串传过去,显示Hellojava。但是,如果传递的level是不是1,那么,就不会输出Hellojava,但是,还是会把mess1和mess2拼接好的字符串传递过去。
下来,看一下Lambda表达式写这段程序。
函数式接口IMyLambda
测试类
与上面普通方法不同的是:上面的会把拼接字符串mess1 + mess2传给showLog函数;
而使用Lambda表达式,仅仅是把参数传递到showLog方法中,如果第一个参数level是1,才会调用接口IMyLambda中的方法buildMess方法,才会进行字符串的拼接。否则,如果不是1,那么就不会调用接口中的方法,不会进行字符串的拼接。所以,Lambda表达式在一定程度上,优化了程序。
二:书写简单
Lambda表达式和匿名内部类很像,比如:
Lambda表达式写法:
匿名内部类写法:
for循环
但是,Lambda仅仅适用于函数式接口,所以,在参数为函数式接口的方法中,我们可以尽量使用Lambda表达式,不仅书写简单,还能优化性能。比如,最有名的Runnable接口的run()方法了
三、应用
1.使用lambda表达式实现interface接口
1.1、当一个接口只有一个方法时,可以使用lambda表达式实现这个接口。1.2、当方法中只有一条语句时,可以不写大括号1.3、方法中超过一条语句时,需要写大括号
2.使用lambda表达式实现Runnable接口
3.使用lambda表达式启动一个Thread线程
不用lambda表达式的实现:
使用lambda表达式的实现:
Stream API
注意:①Stream自己不会存储元素。②Stream不会改变源对象。相反,会返回持有新结果的新Stream。③Stream操作是延迟执行的。这意味着他们会等到需要结果的时候才执行。
操作的三个步骤:1、创建一个流Stream2、中间操作3、终止操作
filter -- 接受Lambda,从流中排除某些元素
limit -- 截断流,使其元素不超过某个给定数量
skip -- 跳过元素,返回一个扔掉了前n个元素的流,若流中元素不足n个,则返回一个空流,与limit互补。
distinct -- 去重,通过hashcode和equals去重。
排序
Stream的终止操作
- allMatch – 检查是否匹配所有元素
- anyMatch – 检查是否至少匹配一个元素
- noneMatch – 检查是否没有匹配所有元素
- findFirst – 返回第一个元素
- count – 返回流中元素的总个数
- max – 返回流中最大值
- min – 返回流中最小值
终止操作:归约reduce
可以将流中的元素反复结合起来,得到一个值
终止操作:收集Collect(很强大)
将流转换成其他格式,接受一个Collector接口的实现,用于给Stream中元素做汇总的操作。
Collector接口中方法的实现决定了如何对流进行收集操作(如收集到List、Set、Map)中,Collectors实用类提供了很多静态方法,可以方便的创建常用收集器实例
map函数的作用就是针对管道流中的每一个数据元素进行转换操作。(映射)
转化大写
转化数字
处理对象数据格式转换
由于map的参数e就是返回值,所以可以用peek函数。peek函数是一种特殊的map函数,当函数没有返回值或者参数就是返回值的时候可以使用peek函数。
并行流
1、并行流的效率是否更高
并行流就是把一个内容分成多个数据块,并用不同的线程分别处理每个数据块的流。
直接使用for循环
JDK8的并行流实现(速度快了10倍)
2、并行流处理结果是否准确
举个例子来说,遍历打印一个存有0 1 2 3 4 5 6 7 8 9的list,如0 1 2 3 4 5 6 7 8 9
打印的结果如下:
并行流
打印的结果如下:
第二次打印的结果如下:
可以看到打印出来的顺序是混乱无规律的。原因是:
并行流内部使用了默认的ForkJoinPool线程池,所以它默认的线程数量就是处理器的数量,通过Runtime.getRuntime().availableProcessors()可以得到这个值。
如果电脑的线程数是12,这意味着并行流最多可以将任务划分为12个小模块进行处理,然后再合并计算得到结果。
打印处理的时候为了提高效率,不分先后顺序,故而造成打印的乱序。
并行流的实现机制:
结论:
当需要遍历的数据,存在强顺序性时,不能使用并行流,如顺序打印0~9;不要求顺序性时,可以使用并行流以提高效率,如将集合中的字符串中的"a"替换成"b"。
Optional类
Optional 类(java.util.Optional) 是一个容器类,代表一个值存在或不存在,原来用null 表示一个值不存在,现在Optional 可以更好的表达这个概念。并且可以避免空指针异常。
常用方法:
- Optional.of(T t) : 创建一个Optional 实例
- Optional.empty() : 创建一个空的Optional 实例
- Optional.ofNullable(T t):若t 不为null,创建Optional 实例,否则创建空实例
- isPresent() : 判断是否包含值
- orElse(T t) : 如果调用对象包含值,返回该值,否则返回t
- orElseGet(Supplier s) :如果调用对象包含值,返回该值,否则返回s 获取的值
- map(Function f): 如果有值对其处理,并返回处理后的Optional,否则返回Optional.empty()
- flatMap(Function mapper):与map 类似,要求返回值必须是Optional