Java 8 Stream The peek() is not working with count()?
By:Roy.LiuLast updated:2019-08-11
Many examples are using the .count() as the terminal operation for .peek(), for example:
Java 8
List<String> l = Arrays.asList("A", "B", "C", "D"); long count = l.stream().peek(System.out::println).count(); System.out.println(count); // 4
Output – It’s working fine.
However, for Java 9 and above, the peek() may print nothing:
Java 9 and above
List<String> l = Arrays.asList("A", "B", "C", "D"); long count = l.stream().peek(System.out::println).count(); System.out.println(count); // 4
Output
Why peek() print nothing now?
Refer to the Java 9 .count() Java docs
An implementation may choose to not execute the stream pipeline (either sequentially or in parallel) if it is capable of computing the count directly from the stream source. In such cases no source elements will be traversed and no intermediate operations will be evaluated.
Since Java 9, if JDK compiler is able computing the count directly from the stream (optimization in Java 9), it didn’t traverse the stream, so there is no need to run peek() at all.
List<String> l = Arrays.asList("A", "B", "C", "D"); // JDK compiler know the size of the stream via the variable l long count = l.stream().peek(System.out::println).count();
To force the peek() to run, just alter some elements with filter() or switch to another terminal operation like collect()
filter()
List<String> l = Arrays.asList("A", "B", "C", "D"); long count = l.stream() .filter(x->!x.isEmpty()) .peek(System.out::println) .count(); System.out.println(count); // 4
Output
collect()
List<String> l = Arrays.asList("A", "B", "C", "D"); List<String> result = l.stream() .peek(System.out::println) .collect(Collectors.toList()); System.out.println(result.size()); // 4
Output
Be careful of mixing .peek() with .count(), the peek() may not work as expected in Java 9 and above.
P.S Tested with Java 12
From:一号门
COMMENTS