有段代码如下,这里我开始用Java Stream 中的map
来修改对象的值
less 代码解读复制代码 retPage.setRecords(retList.stream().map(questionPageVO -> {
questionPageVO.setCreateUserName(userIdAndUserMap.get(questionPageVO.getCreateId()).getUsername());
questionPageVO.setUpdateUserName(userIdAndUserMap.get(questionPageVO.getUpdateId()).getUsername());
return questionPageVO;
}).collect(Collectors.toList()));
但idea提示我这里可以替换为peek
,
替换之后的写法
代码语言:javascript复制less 代码解读复制代码retPage.setRecords(retList.stream().peek(questionPageVO -> {
questionPageVO.setCreateUserName(userIdAndUserMap.get(questionPageVO.getCreateId()).getUsername());
questionPageVO.setUpdateUserName(userIdAndUserMap.get(questionPageVO.getUpdateId()).getUsername());
}).collect(Collectors.toList()));
这样确实更简单整洁了,但peek
这样用真的合适吗? 今天我们就来讲一下peek
的一些不为人知的缺点。
peek的基本定义和使用
- 先来看看
peek
的定义:
swift 代码解读复制代码Stream<T> peek(Consumer<? super T> action);
peek方法接受一个Consumer参数,返回一个Stream结果。
而Consumer
是一个FunctionalInterface
,它需要实现的方法是下面这个:
arduino 代码解读复制代码void accept(T t);
accept
对传入的参数T进行处理,但是并不返回任何结果。
peek
的基本使用
csharp 代码解读复制代码public static void baseUse() {
List<Integer> list = Stream.of(1,2,3)
.peek(System.out::println)
.collect(Collectors.toList());
System.out.println(list);
}
输出内容:
代码语言:javascript复制csharp 代码解读复制代码1
2
3
[1, 2, 3]
3. peek
的流式处理
csharp 代码解读复制代码public static void peekForEach() {
Stream.of(1,2,3)
.peek(System.out::println)
.forEach(e -> System.out.println("forEach:" e));
}
输出内容:
代码语言:javascript复制makefile 代码解读复制代码1
forEach:1
2
forEach:2
3
forEach:3
通过输出内容也可以看出,流式处理流程,是对应流中每一个元素,分别经历peek
和forEach
操作(即一个元素执行完所有流程),而不是等peek
完所有元素元素后再执行forEach
坑一:Stream的懒执行策略
之所以有流操作,是因为有时候处理的数据比较多,无法一次性加载到内存中。
为了优化stream的链式调用效率,stream还提供了一个懒加载策略。
什么是懒加载呢?
懒加载也叫intermediate operation, 在stream
的方法中,大部分都是懒加载,另外部分则是terminal operation, 例如collect
、count
等,当有这种非懒加载的方法调用时,整个链式都会被执行,如开始的baseUse
示例。
但peek
和map
,都是懒加载方法,即intermediate operation。
intermediate operation的特点是立即返回,如果最后没有以terminal operation结束,intermediate operation实际上是不会执行的。
贴个官方解释图
让我们来看这个示例:
代码语言:javascript复制csharp 代码解读复制代码public static void peekLazy() {
Stream.of(1,2,3)
.peek(e -> System.out.println("peek lazy: " e));
}
执行之后,结果什么都没输出,表示peek
中的逻辑没有被调用这里就是很大的一个坑,使用的时候要注意。
同理这里map
也是一样。
csharp 代码解读复制代码public static void mapLazy() {
Stream.of(1,2,3)
.map(e -> {
e = e 1;
System.out.println("map lazy: " e);
return e;
});
}