Java8 Stream Filter – considering list elements whose are added after filter stream creation

  • A+
Category:Languages
List<String> strList = new ArrayList<>(); strList.add("Java"); strList.add("Python"); strList.add("Php");  Stream<String> strStream = strList.stream();  Stream<String> jFilter = strStream.filter(str -> str.startsWith("J"));  strList.add("JavaScript"); // element added after filter creation strList.add("JQuery"); // element added after filter creation  System.out.println(Arrays.toString(jFilter.toArray()));  

Output:

[Java, JavaScript, JQuery] 

Why JavaScript, JQuery appeared in filter result even though they are added after filter stream creation.

 


Short Answer

You're assuming after this point:

Stream<String> jFilter = strStream.filter(str -> str.startsWith("J")); 

That a new stream of the elements starting with "J" are returned i.e. only Java. However this is not the case;

streams are lazy i.e. they don't perform any logic unless told otherwise by a terminal operation.

The actual execution of the stream pipeline starts on the toArray() call and since the list was modified before the terminal toArray() operation commenced the result will be [Java, JavaScript, JQuery].

Longer Answer

here's part of the documentation which mentions this:

For well-behaved stream sources, the source can be modified before the terminal operation commences and those modifications will be reflected in the covered elements. For example, consider the following code:

 List<String> l = new ArrayList(Arrays.asList("one", "two"));  Stream<String> sl = l.stream();  l.add("three");  String s = sl.collect(joining(" "));   

First a list is created consisting of two strings: "one"; and "two". Then a stream is created from that list. Next the list is modified by adding a third string: "three". Finally the elements of the stream are collected and joined together. Since the list was modified before the terminal collect operation commenced the result will be a string of "one two three". All the streams returned from JDK collections, and most other JDK classes, are well-behaved in this manner;

Comment

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: