Intermediate operation in Java streams [duplicate]

心不动则不痛 提交于 2021-02-18 19:20:05

问题


In java 8, I am using Streams to print the output, but size is coming as 0. Why?

public class IntermediateryAndFinal {
    public static void main(String[] args) {
        Stream<String> stream = Stream.of("one", "two", "three", "four", "five");

        Predicate<String> p1 = Predicate.isEqual("two");
        Predicate<String> p2 = Predicate.isEqual("three");

        List<String> list = new ArrayList<>();

        stream.peek(System.out::println)
            .filter(p1.or(p2))
            .peek(list::add);
        System.out.println("Size = "+list.size());
    }
}

回答1:


Ideally you should not mutate an external list, instead you can use Collectors.toList() to collect it in a list:

List<String> list = stream.peek(System.out::println)
            .filter(p1.or(p2))
            .collect(Collectors.toList()); // triggers the evaluation of the stream
System.out.println("Size = "+list.size());

In your example, streams are evaluated only when a terminal operation like

allMatch()
anyMatch() 
noneMatch() 
collect() 
count() 
forEach() 
min() 
max() 
reduce()

are encountered.




回答2:


Since you haven't yet completed the stream operation i.e. peek is an intermediate operation. You must use a terminal operation for that to be executed still.

Suggestion: Instead perform such operation using terminal operation such as collect

List<String> list = stream.peek(System.out::println)
        .filter(p1.or(p2))
        .collect(Collectors.toList());

Additionally: Adding a peek post filter to observe the values could be a little tricky in observation, as for the following code

List<String> list = stream.peek(System.out::println)
        .filter(p1.or(p2))
        .peek(System.out::println) // addition
        .collect(Collectors.toList());

the output would look like :

one
two
two // filtered in
three
three // filtered in
four
five



回答3:


The streams are lazy. You mast call a terminal operation like forEach:

stream.peek(System.out::println)
      .filter(p1.or(p2))
      .forEach(list::add);

In case you want to use peek as intermediary operation for debugging purposes then you must call a terminal operation afterwards:

stream.peek(System.out::println)
      .filter(p1.or(p2))
      .peek(list::add);
      .<any terminal operation here>();

Btw, if you want just store all the filtered values in a list, then better use collect(toList()).




回答4:


All you've done with filter and peek is set up a chain of actions to apply to the stream. You haven't actually caused any of them to run yet. You have to add a terminal operation such as count. (Another answer suggested using forEach to add to the list, but I think you're specifically trying to use the intermediate operation peek.)



来源:https://stackoverflow.com/questions/54510305/intermediate-operation-in-java-streams

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