Stream操作中peek的使用
前言
最近项目中遇到一个需求,一个List<entity>
,实体里有多个字段,只有部分有值,需要遍历这个实体,给其他的字段也赋值后在更新会数据库,首先想到的就是stream流操作
过程
1 | waitDevs.parallelStream().map(rec -> { |
一开始是这么写的,map里设置完,return返回这个实体,但是idea提示了可以用peek这个操作,按照它的提示最后改进了这个代码
1 | waitDevs.parallelStream().peek(rec -> { |
不需要return了,下面说下这俩的区别
区别
1 | Stream peek(Consumer<? super T> action) |
返回由该流的元素组成的流,另外在从生成的流中消耗元素时对每个元素执行提供的操作。
1 | Stream map(Function<? super T,? extends R> mapper) |
返回由给定函数应用于此流的元素的结果组成的流。
- 两个函数都是中间操作,都非常的‘懒’,没有对Stream的终止操作,两个函数都不会工作。
- peek函数的存在仅仅是为了debug,而map是Stream的一个核心函数,两个函数的地位不同。
- 两个函数的返回值都是一个新的Stream,但是两个函数的参数(peek是Consumer,map是Function)起作用的时机不同。map的Function在生成新的Stream之前被执行,新Stream中的元素是上游Stream中元素经Function作用后的值。peek函数的Consumer工作在生成Stream之后,下一节详细讲解两个函数执行时机。
peek和map修改Stream的元素
map函数对Stream中元素执行的是映射操作,会以新的元素(map的结果)填充新的Stream,严格的讲map不是修改原来的元素。
peek只能消费Stream中的元素,是否可以更改Stream中的元素,取决于Stream中的元素是否是不可变对象。如果是不可变对象,则不可修改Stream中的元素;如果是可变对象,则可以修改对象的值,但是无法修改对象的引用。
总结
举个很简单的例子,比如 Stream.of("one", "two", "three", "four")
流中是字符串,如果peek中修改了字符串,则是无效的,但是流中如果是个可变对象,就是可以修改的