Possible side effect of Stream.peek changing state and why not use it like this

安稳与你 提交于 2019-12-24 00:48:39

问题


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.

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).

Here is what Javadoc says:

This method exists mainly to support debugging, where you want to see the elements as they flow past a certain point in a pipeline:

And then:

Parameters: action - a non-interfering action to perform on the elements as they are consumed from the stream.

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.

Here is the code that uses 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) Can the above code have any side effect?

2) Why not use peek in such a way. The Javadoc does not seem to not allow it?


回答1:


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 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.

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.

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.



来源:https://stackoverflow.com/questions/47356992/possible-side-effect-of-stream-peek-changing-state-and-why-not-use-it-like-this

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!