Main Tutorials

Java 8 Stream – The peek() is not working with count()?

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.


A
B
C
D
4

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


4

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


A
B
C
D
4
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


A
B
C
D
4

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

References

About Author

author image
Founder of Mkyong.com, love Java and open source stuff. Follow him on Twitter. If you like my tutorials, consider make a donation to these charities.

Comments

Subscribe
Notify of
2 Comments
Most Voted
Newest Oldest
Inline Feedbacks
View all comments
Udo
5 days ago

This is indeed an incompatible change in Java 9 compared to Java 8! In Java 8 Stream.count() was equivalent to mapToLong(e -> 1L).sum() which implies that the stream was fully iterated. Now count() can short-circuit the stream so that Java 8 code is not working anymore in Java 9!What’s more, this change is not even mentioned in the Java 9 release notes!
Do you know of other incompatible changes in Java 9 or above?

Lokeshwar
2 years ago

thanks for the article 🙂