Reputation: 13835
This question is somhow related to Java 8 Stream - Filter and foreach method not printing as expected
I am working with sorted, filter and map method of Java 8 Stream. Keeping in mind how filter and map works as specified in the answers of above mentioned question, I tried the sorted method as follows:
Stream.of("d2", "a2", "b1", "b3", "c")
.sorted((s1, s2) -> {
System.out.printf("sort: %s; %s\n", s1, s2);
return s1.compareTo(s2);
})
.filter(s -> {
System.out.println("filter: " + s);
return s.startsWith("a");
})
.map(s -> {
System.out.println("map: " + s);
return s.toUpperCase();
})
.forEach(s -> System.out.println("forEach: " + s));
And the output i got is:
sort: a2; d2 sort: b1; a2 sort: b1; d2 sort: b1; a2 sort: b3; b1 sort: b3; d2 sort: c; b3 sort: c; d2 filter: a2 map: a2 forEach: A2 filter: b1 filter: b3 filter: c filter: d2
That is, now the sorted method is executed for the complete loop and then filter and map functions are executed on individual items. As all the three are intermediate functions, so all should have worked the same manner. Is the execution order fine or not? I am not getting what i am doing wrong.
Upvotes: 3
Views: 454
Reputation: 43052
https://docs.oracle.com/javase/8/docs/api/java/util/stream/package-summary.html
Side-effects
Side-effects in behavioral parameters to stream operations are, in general, discouraged, as they can often lead to unwitting violations of the statelessness requirement, as well as other thread-safety hazards.
[...] Further, the ordering of those effects may be surprising. Even when a pipeline is constrained to produce a result that is consistent with the encounter order of the stream source (for example,
IntStream.range(0,5).parallel().map(x -> x*2).toArray() must produce [0, 2, 4, 6, 8])
, no guarantees are made as to the order in which the mapper function is applied to individual elements, or in what thread any behavioral parameter is executed for a given element.
Upvotes: 3
Reputation: 372
"it depends". Stream operations can interleave because each stage can emit items as soon as their order is evident. In the case of filtering and mapping, each item can be processed and swallowed or passed.
In the case of sorting, it all depends on the sorting algorithm. If the sorting was implementing as "find the minimum of all elements with n-1 comparisons, emit the minimum, repeat with the rest", the sorting would indeed interleave with the filtering and mapping. But looking at your output, it looks more like an insertion sort (with binary search or some search tree for the insertion point): a2/d2 are compared resulting (a2, d2); b1 is compared to a2 first and then d2 to insert it between the two yielding (a2,b1,d2), b3 is compared to b1, then d2 and inserted to (a2,b1,b3,d2) and so on. This makes sense as it yields an expected O(nlogn) time for sorting (compared to O(n^2) for the repeated minimum finding), but it cannot emit anything until the last element is inserted. That is, sorting must complete before filtering can start.
Upvotes: 3