2016-09-02 2 views
1

Schools이 많고 Students이 많고 Classes이 많은 SchoolDistrict이 있다고 가정 해 봅시다.컬렉션이있는 컬렉션의 컬렉션 수를 계산하려고합니다

나는 SchoolDistrict가 주어진 클래스의 수를 계산하고 싶습니다.

자바 7 방법과 같이 될 것이다 :

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

나는 자바 (8)가 눈에 좀 더 쉽게 이런 종류의 일을 해야하는 스트림을 제공 것을 알고있다.

하지만 어떻게해야하는지 알아내는 데 어려움이 있습니다.

수취인?

EDIT : 누군가 이것을 this post의 복제물로 표시했는데, 그 예가 단지 2 단계로 깊게 나왔다는 것이 나는 믿을 수 없습니다 (국가 별). 내 질문은 네 단계로 깊어가는 문제와 관련이 있습니다 (학교에서 학생을위한 학교에서 학생까지)

+0

@azurefrog 거의,하지만 내 컬렉션 쿼리를 사용하여 한 레벨 더 깊숙이 들어가야합니다. – Trevor

+0

다음과 같이 시도해보십시오. : schoolDistrict.stream(). mapToInt (school -> school.getStudents(). getClasses(). size)) .sum();' – Orin

+0

@ Orin2005 getStudents(). getClasses()'getStudents()'는 콜렉션을 반환하므로'Class'es를 포함하지 않습니다. – Trevor

답변

5

이 작업 수행 산세의 람다를 얻을 방법 참조를 사용 각 학생을 위해 각 클래스를 스트리밍하고 반복적으로 클래스를 세는 것보다 효율적입니다.

+0

이것은 좀 예쁘게 보입니다. – Kayaman

+0

나는'.flatMap (List :: stream)을 생각하지 않는다.지도 부분은 작동합니다 – Trevor

+0

@ 카야 만 방법 참조 (람다 없음) 만 사용하는 것이 더 많은 단계를 필요로하지만 깨끗하게 보이고 쉽게 따라갈 수 있습니다. IMHO – Bohemian

4

schoolDistrict.stream().flatMap(school -> school.getStudents().stream())을 사용하면 Stream<Student>을 얻을 수 있습니다. 두 번째로 flatMap()을 수행하면 Stream<YourClass>이됩니다. 이때 중첩 된 콜렉션의 각 엔티티를 처리해야합니다. 금액 만 계산하면 끝 작동으로 mapToInt()sum()을 사용할 수 있습니다.

따라서 flatMap()은 중첩 된 컬렉션을 훼손하거나 "평평하게 만드는"비결입니다.

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

참고도 물론 다음 sum()을 적용하는 크기 각 학생의 수업의IntStream로의 전환이다 :

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

flatMap은 뭔가 관련이 있다는 것을 알았지 만, flapMap 람다 함수 안에 여분의'.stream()'을 추가하고있었습니다. 많은 감사합니다 – Trevor

관련 문제