2016-09-02 1 views
1

Предположим, у меня есть SchoolDistrict, у которого много Schools, у которого много Students, у которых много Classes.Я хочу рассчитать количество коллекций в коллекции, в коллекции с потоками

Я хочу рассчитать количество уроков, предоставленных SchoolDistrict.

Java-7 путь будет выглядеть примерно так:

Integer classCount = 0; 
for (School school : schoolDistrict) 
{ 
    for (Student student : school.getStudents()) 
    { 
     classCount += student.getClasses().size(); 
    } 
} 

Я знаю, что Java 8 приносит потоки, которые, как предполагается, чтобы сделать такого рода вещи немного легче на глазах.

Но мне трудно понять, как это сделать.

Любые берущие?

EDIT: кто-то отметил это как дубликат this post. Я не верю, что этот пример прошел только на 2 уровнях (страны в регионы). Мой вопрос связан с проблемой, которая идет на четыре уровня в глубину (Школьные школы для учащихся до классов)

+0

@azurefrog почти, но мне нужно идти на один уровень глубже с моим запросом на сбор – Trevor

+0

Возможно, попробуйте что-то вроде этого: 'schoolDistrict.stream(). MapToInt (school -> school.getStudents(). GetClasses(). Size ()) .sum(); ' – Orin

+0

@ Orin2005 вы не можете делать' getStudents(). getClasses() 'as' getStudents() 'возвращает коллекцию, которая в этом случае не содержит' Class'es. – Trevor

ответ

5

Это использует ссылки метод, чтобы получить работу SANS лямбды:

int classCount = schoolDistrict.stream() 
    .map(School::getStudents) 
    .flatMap(Collection::stream) 
    .map(Student::getClasses) 
    .mapToInt(Collection::size) 
    .sum(); 

Обратите внимание также переключатель на IntStream из размеров классов каждого студента, то применяя sum(), что, конечно, более эффективны, чем потоковое воспроизведение каждого класса для каждого ученика и подсчет классов итеративно.

+0

Это выглядит немного красивее. – Kayaman

+0

Я не думаю, что '.flatMap (List :: stream).map' part будет работать – Trevor

+0

@ Kayaman требуется больше шагов для использования только ссылок на методы (нет lambdas), но я согласен, что он выглядит более чистым, и вы можете легко следовать ему. IMHO – Bohemian

4

Вы можете использовать schoolDistrict.stream().flatMap(school -> school.getStudents().stream()) для получения Stream<Student>. Вы также можете сделать второй flatMap(), чтобы получить Stream<YourClass>. Это когда вам нужно обработать каждый объект вложенных коллекций. Если вам нужно только подсчитать суммы, вы можете использовать mapToInt() и sum() в качестве конечной операции.

Таким образом, flatMap() является секретом для неупорядочения или «сглаживания» вложенных коллекций.

Stream<MyClass> stream = schoolDistrict.stream().flatMap(s -> s.getStudents().stream()).flatMap(s -> s.getClasses().stream()); 
int count = stream.count(); 
+0

Я знал, что flatMap имеет к этому какое-то отношение ... но он добавлял в дополнительную '.stream()' внутри функции lambda flapMap, которую я отсутствовал. Большое спасибо – Trevor

Смежные вопросы