membersound membersound - 5 days ago 4
Java Question

How to count matches on a stream filter?

How can I count the matches of a stream filter? I'm trying to refactor the following code to java8

stream
:

//java7
int i = 0;
for (Node node : response.getNodes()) {
Integer id = node.getId();
if (id != null) {
node.setContent("This is the id: " + id);
i++;
}
}

//java8
response.getNodes().stream()
.filter(node -> node.getId() != null)
.forEach(node -> node.setValue("This is the id: " + node.getId()));


How can I now get the count of filtered elements that were applied?
Sidequestion: in the old code I can reuse the
Integer id
multiple times. How can I achieve the same with streams?

Answer

Since setValue is a side-effect function, you can use peek:

long i = response.getNodes()
                 .stream()
                 .filter(node -> node.getId() != null)
                 .peek(node -> node.setValue("This is the id: " + node.getId()))
                 .count();

I'm not a fan of this approach because peak is meant to use for debugging purpose (this would do the trick). Note that in Java 9, count() may be able to not execute the stream pipeline if it can compute the count directly from the source (I don't think it's the case here, since you apply a filtering but it's good to keep it in mind).

Sidequestion: in the old code I can reuse the Integer id multiple times. How can I achieve the same with streams?

It depends on your use-case, since the API doesn't have tuples your best chance is to create a class, let's say Tuple2, so that you can map each node to a new tuple and reuse the id.

Something like:

.stream().map(node -> new Tuple2<>(node, node.getId()).moreStreamOps(...);
                                                      ^
                                                      |
                 at that point you have a Stream<Tuple2<Node, Integer>> 
                 from which you can grab the id with Tuple2#getSecond

In your case, if you stay with a stream of nodes, you can just grab the id with getId() at any time.