Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Java 8 Streams: count all elements which enter the terminal operation

I wonder whether there is a nicer (or just an other) approach to get the count of all items that enter the terminal operation of a stream instead of the following:

Stream<T> stream = ... // given as parameter
AtomicLong count = new AtomicLong();
stream.filter(...).map(...)
      .peek(t -> count.incrementAndGet())

where count.get() gives me the actual count of the processed items at that stage.

I deliberately skipped the terminal operation as that might change between .forEach, .reduce or .collect. I do know .count already, but it seems to work well only if I exchange a .forEach with a .map and use the .count as terminal operation instead. But it seems to me as if .map is then misused.

What I don't really like with the above solution: if a filter is added after it, it just counts the elements at that specific stage, but not the ones that are going into the terminal operation.

The other approach that comes to my mind is to collect the filtered and mapped values into a list and operate on that and just call list.size() to get the count. However this will not work, if the collection of the stream would lead to an error, whereas with the above solution I could have a count for all processed items so far, if an appropriate try/catch is in place. That however isn't a hard requirement.

like image 213
Roland Avatar asked Apr 27 '17 09:04

Roland


People also ask

Which terminal operation can be used to count the number of items in the stream?

long count() returns the count of elements in the stream.

How do I count the number of elements in Java 8?

Java 8 | Collectors counting() with ExamplesCollectors counting() method is used to count the number of elements passed in the stream as the parameter. It returns a Collector accepting elements of type T that counts the number of input elements. If no elements are present, the result is 0.

What are the terminal operations in streams?

The Stream API gives you two terminal operations to find an element: findFirst() and findAny() . These two methods do not take any argument and return a single element of your stream.

What is terminal operation in Java stream?

The Java Stream API's terminal operations return the final result of iterating through all the elements in the stream, and providing the non-terminal and terminal operations to the elements. The result of the terminal operation is returned after the last element in the stream has been processed.


1 Answers

It seems you already have the cleanest solution via peek before the terminal operation IMO. The only reason I could think that this is needed is for debug purposes - and if that is the case, than peek was designed for that. Wrapping the Stream for that and providing separate implementations is way too much - besides the huge amount of time and later support for everything that get's added to Streams.

For the part of what if there is another filter added? Well, provide a code comment(lots of us do that) and a few test cases that would otherwise fail for example.


Just my 0.02$

like image 91
Eugene Avatar answered Sep 20 '22 01:09

Eugene