2014-04-06 2 views
6

Я хочу перебирать коллекцию коллекций. С Guava я бы сделал это:Объединение коллекций с Java 8

import static com.google.collections.Iterables.*; 

class Group { 
    private Collection<Person> persons; 
    public Collection<Person> getPersons(); 
} 

class Person { 
    private String name; 
    public String getName(); 
} 

Collection<Group> groups = ...; 
Iterable<Person> persons = concat(transform(groups, Group::getPersons())); 
Iterable<String> names = transform(persons, Person::getName); 

Но как я могу сделать то же самое с потоками Java 8?

groups.stream().map(Group::getPersons())...? 

ответ

6

Вы можете достичь этого с плоским отображением всех элементов потока в ваш поток.

Позвольте мне объяснить этот код:

groups.stream() 
     .flatMap(group -> group.getPersons().stream()); 

Что вы делаете здесь, это:

  1. Получить Stream<Collection<Group>>.
  2. После этого плоская карта каждый полученный Stream<Person>, от Group, обратно в ваш первоначальный поток, который имеет тип Stream<Person>.

Теперь после flatMap() вы можете делать все, что хотите, с помощью полученных Stream<Person>.

+1

Будет ли эта оценка по-прежнему ленивой? Если я хочу, например, узнать только имя первого человека? –

+1

@PhilippJardas Да, * most * 'Stream ' операции ленивы. Вы можете узнать больше о том, какие из них не ленивы в javadoc, например 'sorted()' не ленив. – skiwi

+0

Отлично, спасибо! Хотя есть несколько правильных ответов, я соглашусь с этим, потому что он был первым. :-) –

6
Stream<Person> persons = groups.stream().flatMap(g -> g.getPersons().stream()); 
+0

Хмммэп, не очень «элегантный»;) Я думаю, кто-то уже придумывает «Streams.concat()» ... Хотя они должны быть осторожны с «.characteristics» этого потока() ' – fge

+4

Как это не изящно? Это классическая функциональная идиома, и она полна лени. Почему Streams.concat() будет более элегантным? –

+1

+1 Если вы попытались реализовать 'concat', вы попали бы в' flatMap (x-> x) '. В Clojure я фактически не мог решить, нужно ли '(применять concat ...)' или '(flatmap identity ...)'. –

2

Я думаю, что вам нужно flatMap:

Stream<Person> persons = groups.stream().flatMap(g -> g.getPersons().stream()); 
Смежные вопросы