2015-10-24 19 views
8

Supponiamo di avere un elenco di paesi: List<Country> e ogni paese ha un riferimento a un elenco delle sue regioni: List<Region> (ad esempio, nel caso degli Stati Uniti). Qualcosa del genere:API Java Stream: contare gli elementi di un elenco annidato

USA 
    Alabama 
    Alaska 
    Arizona 
    ... 

Germany 
    Baden-Württemberg 
    Bavaria 
    Brandenburg 
    ... 

In Java "vecchio-vecchio" possiamo contare tutte le regioni, ad es. in questo modo:

List<Country> countries = ... 
int regionsCount = 0; 

for (Country country : countries) { 
    if (country.getRegions() != null) { 
     regionsCount += country.getRegions().size(); 
    } 
} 

È possibile raggiungere lo stesso obiettivo con Java 8 Stream API? Ho pensato a qualcosa di simile a questo, ma non so come contare gli elementi di liste annidate utilizzando count() modalità di flusso API:

countries.stream().filter(country -> country.getRegions() != null).??? 
+2

IMHO questa soluzione @fabian dovrebbe essere preferito. 'List :: size' è un'operazione' O (1) 'mentre usare un' flatMap' su ogni lista è un'operazione 'O (n)'. – Flown

risposta

17

Si potrebbe utilizzare map() per ottenere un Stream di liste regione e poi mapToInt a ottenere il numero di regioni per ogni paese. Dopo che l'uso sum() per ottenere la somma di tutti i valori nella 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(); 

Nota: Il vantaggio di utilizzare getRegions prima della filtrazione è che non c'è bisogno di chiamare più getRegions di una volta.

+5

Nota a margine, puoi usare 'Objects :: nonNull' invece di' rs -> rs! = Null' – Tunaki

4

Si può mappare ogni paese per numero di regioni e quindi ridurre il risultato utilizzando somma:

countries.stream() 
    .map(c -> c.getRegions() == null ? 0 : c.getRegions().size()) 
    .reduce(0, Integer::sum); 
+3

.reduce (Intero :: somma) :) –

+0

Risolto il mio problema! – Daria

0

Si potrebbe anche usare come flatMap():

countries.stream().map(Country::getRegions).flatMap(List::stream).count(); 

where, 

map(Country::getRegions) = returns a Stream<List<Regions>> 
flatMap(List::stream) = returns a Stream<Regions> 
Problemi correlati