peek(窥视)和map(转换)顾名思义:一个是看一眼参数,一个是转化参数。
1. 区别
peek和map的区别:均作为流处理的中间操作,但是两个的内部处理函数不同,一个为“消费元素”,另一个为“映射元素”。
Stream<T> peek(Consumer<? super T> action);
<R> Stream<R> map(Function<? super T, ? extends R> mapper);
peek和foreach的区别:peek作为中间操作,而foreach作为终端操作;
Stream<T> peek(Consumer<? super T> action);
void forEach(Consumer<? super T> action);
2. peek的使用场景
在Java doc中这样描述:“元素存在的目的为了进行debug”
API Note:
This method exists mainly to support debugging, where you want to see the elements as they flow past a certain point in a pipeline:
那么能否使用peek做其他操作呢?
例如:对内部的元素进行修改。
public class TestPeek {
public static void main(String[] args) {
List<User> lists = new ArrayList<>();
lists.add(new User("a"));
lists.add(new User("b"));
lists.add(new User("c"));
List<User> collect = lists.stream().peek(p -> {
p.setName("1"+p.getName());
}).collect(Collectors.toList());
}
@Data
public static class User {
private String name;
public User(String name) {
this.name = name;
}
}
}
sonarlint中的描述谨慎使用peek().png
根据其 JavaDocs,中间 Stream 操作 java.util.Stream.peek() “存在主要是为了支持调试”目的。
与其他中间 Stream 操作的一个主要区别是 Stream 实现可以自由地跳过对 peek() 的调用以进行优化。 这可能导致 peek() 仅针对 Stream 中的某些元素或没有元素被意外调用。
因此,在没有仔细考虑的情况下依赖 peek() 会导致代码容易出错。
此规则为 peek() 的每次使用提出了一个问题,以确保团队对其进行挑战和验证以用于生产调试/日志记录目的。
3. 完全可以使用map或者forEach进行取代
上面的场景,使用forEach进行取代:
lists.forEach(p->p.setName("1"+p.getName()));
所以,还是谨慎使用peek()函数来进行操作吧!!