问题描述
我在另一个Stackoverflow上提出的解决方案正在使用Stream.peek操作,但似乎仍然是正确的,因为它在 Stream.peek
方法中改变了状态。
A solution that I came up on another Stackoverflow question that is using Stream.peek operation works but still seems like is not right because it mutates state in the Stream.peek
method.
在研究时(和) Stream.peek
用法是否可以改变状态我仍然不完全相信 Stream。 peek
不应该改变状态(包括作为 Stream
的来源的集合状态)。
While researching (here and here) on Stream.peek
usage whether it is ok to mutate state I am still not fully convinced that Stream.peek
should not mutate state (including state of collection that is source of the Stream
).
以下是说:
然后:
对于表现良好的非干扰
流源,可以在终端
操作开始之前修改源,并且这些修改将反映在
覆盖的元素。从JDK集合返回的所有流和大多数其他JDK类的
都以这种方式表现良好。
For well-behaved non-interfering stream sources, the source can be modified before the terminal operation commences and those modifications will be reflected in the covered elements.All the streams returned from JDK collections, and most other JDK classes, are well-behaved in this manner.
似乎非干扰操作确实包括更改流中的收集状态。
Seems like non-interfering action does includes changing the state of collection in the stream.
这是代码使用 Stream.peek
。
Map< String, List<Test> > userTests = new HashMap<>();
Map< String, List<Test> > filtered = userTests.entrySet().stream()
.peek( e -> e.setValue( modifyListAndReturnIt( e.getValue() ) ) )
.filter( e -> !e.getValue().isEmpty() ) //check if modified list in peek has been emptied
.collect( Collectors.toMap(p -> p.getKey(), p -> p.getValue() ) );
public static List<Test> modifyListAndReturnIt(List<Test> list){
if (somecondition) list.clear();
return list;
}
1)上述代码是否有任何副作用?
1) Can the above code have any side effect?
2)为什么不以这种方式使用偷看。 Javadoc似乎不允许它?
2) Why not use peek in such a way. The Javadoc does not seem to not allow it?
推荐答案
你似乎做什么看起来无害 Brian Goetz在 。
What you seem to do looks harmless as Brian Goetz states in comment here.
现在问题是,如果你在其中做副作用 - 你会发现这些副作用实际上发生。所以,假设您想要改变某些对象的某些属性,如下所示:
Now the problem with peek is that if you do side effects inside it - you would expect these side effects to actually happen. So, suppose you would want to alter some property of some object like this:
myUserList.stream()
.peek(u -> u.upperCaseName())
.count()
In java-8你的 peek
确实会在9中调用 - 它不是 - 没有必要调用 peek
这里因为无论如何都可以计算出它的大小。
In java-8 your peek
would be indeed called, in 9 - it is not - there is no need to call peek
here since the size can be computed without it anyway.
当你在同一条路径上时,想象一下你的终端操作是短路的,比如 findFirst
或 findAny
- 您不将处理源的所有元素 > - 您可能会通过管道获得其中的一些。
While being on the same path, imagine that your terminal operation is a short-circuit one, like findFirst
or findAny
- you are not going to process all elements of the source - you might get just a few of them through the pipeline.
如果您的 peek
依赖于遭遇订单,即使您的终端操作不是,也可能会变得更加奇怪一个短路的。并行处理的中间操作没有遭遇顺序,而终端处理则没有。想象一下您可能面临的惊喜。
Things might get even stranger if your peek
would rely on a encounter order even if your terminal operation would not be a short-circuit one. The intermediate operations for parallel processing do not have an encounter order, while the terminal ones - do. Imagine the surprises you might be facing.
这篇关于Stream.peek改变状态的可能副作用以及为什么不这样使用它的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!