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.
long count() returns the count of elements in the stream.
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.
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.
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.
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$
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With