Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Java Stream API - count items of a nested list

Let's assume that we have a list of countries: List<Country> and each country has a reference to a list of its regions: List<Region> (e.g. states in the case of the USA). Something like this:

USA   Alabama   Alaska   Arizona   ...  Germany   Baden-Württemberg   Bavaria   Brandenburg   ... 

In "plain-old" Java we can count all regions e.g. this way:

List<Country> countries = ... int regionsCount = 0;  for (Country country : countries) {     if (country.getRegions() != null) {         regionsCount += country.getRegions().size();     } } 

Is it possible to achieve the same goal with Java 8 Stream API? I thought about something similar to this, but I don't know how to count items of nested lists using count() method of stream API:

countries.stream().filter(country -> country.getRegions() != null).??? 
like image 316
dominik Avatar asked Oct 24 '15 11:10

dominik


People also ask

How do I use count in stream API?

1. Stream count() API. The Stream interface has a default method called count() that returns a long value indicating the number of matching items in the stream. To use the count() method, call it on any Stream instance.

How do I print list values in stream?

There are 3 ways to print the elements of a Stream in Java: forEach() println() with collect() peek()

How do you sum a stream in Java?

Using Stream.collect() The second method for calculating the sum of a list of integers is by using the collect() terminal operation: List<Integer> integers = Arrays. asList(1, 2, 3, 4, 5); Integer sum = integers. stream() .

How do you count a method in Java?

The counting() method of the Java 8 Collectors class returns a Collector accepting elements of type T that counts the number of input elements.


2 Answers

You could use map() to get a Stream of region lists and then mapToInt to get the number of regions for each country. After that use sum() to get the sum of all the values in the IntStream:

countries.stream().map(Country::getRegions) // now it's a stream of regions                   .filter(rs -> rs != null) // remove regions lists that are null                   .mapToInt(List::size) // stream of list sizes                   .sum(); 

Note: The benefit of using getRegions before filtering is that you don't need to call getRegions more than once.

like image 128
fabian Avatar answered Sep 18 '22 09:09

fabian


You may map each country to number of regions and then reduce result using sum:

countries.stream()   .map(c -> c.getRegions() == null ? 0 : c.getRegions().size())   .reduce(0, Integer::sum); 
like image 38
Vasily Liaskovsky Avatar answered Sep 17 '22 09:09

Vasily Liaskovsky