2016-01-24 27 views
2

假設你的學生招收到課程集團通過將Java 8

Class Student{ 
    ArrayList<Course> courses; 
} 
Class Course{ 
    String id; 
    String name; 
} 

如何使用GROUPBY功能與Java 8到參加特定課程

回答

4

學生的列表,你要同學生進行分類不同的組,groupingBy收集器在這裏不適合(它將每個流元素精確地放到一個組中)。

這將是更有效的通過forEach創建一個可變的容器(如HashMap)和填充它:

Map<Course, List<Student>> result = new HashMap<>(); 
students.forEach(student -> student.courses.forEach(
     course -> result.computeIfAbsent(course, c -> new ArrayList<>()).add(student))); 

如果你想使用groupingBy您可以將不是學生,但學生當然對,儘管您需要執行下游收集步驟:

import static java.util.stream.Collectors.*; 

Map<Course, List<Student>> result = students.stream() 
    .<Map.Entry<Course, Student>>flatMap(
     student -> student.courses.stream() 
          .map(course -> new AbstractMap.SimpleEntry<>(course, student))) 
    .collect(groupingBy(Map.Entry::getKey, mapping(Map.Entry::getValue, toList()))); 

看起來有點醜陋。我StreamEx庫增加了一些快捷方式,這樣的場景:

Map<Course, List<Student>> result = StreamEx.of(students) 
     .cross(s -> s.courses.stream()).invert().grouping(); 

這看起來好多了,但普通的解決方案看起來還是更好的是(並且不需要第三方庫)。

+0

謝謝Tagir Valeev.That很有用 –

+0

顯式類型'>'不應該是必需的。 – Holger

1

我不得不承認,我使用@ tagir-valeev回答的想法。
創建一個簡單的類

public class CourseStundentPair { 
    private Course course; 
    private Student student; 

    public CourseStundentPair(Course course, Student student) { 
     this.course = course; 
     this.student = student; 
    } 
    ... 
    } 

這將使得代碼更conice和可讀性。
只是出於說服我加名外地學生

import static java.util.stream.Collectors.*; 

public class TestCourse { 

    public static void main(String[] args) { 
     Student student1 = new Student("1", "Student1"); 
     Student student2 = new Student("2", "Student2"); 
     Student student3 = new Student("3", "Student3"); 
     Student student4 = new Student("4", "Student4"); 
     Course course1 = new Course("c1", "English"); 
     Course course2 = new Course("c2", "Mathematics"); 
     Course course3 = new Course("c3", "Literature"); 
     student1.getCourses().add(course1); 
     student1.getCourses().add(course2); 
     student1.getCourses().add(course3); 

     student2.getCourses().add(course1); 
     student2.getCourses().add(course2); 
     student3.getCourses().add(course1); 

     List<Student> students = new ArrayList<>(); 
     students.add(student1); 
     students.add(student2); 
     students.add(student3); 
     students.add(student4); 

     final Map<Course, List<Student>> courseToStudents = students.stream() 
      .flatMap(s -> s.getCourses().stream().map(c -> new CourseStundentPair(c,s))) 
      .collect(groupingBy(CourseStundentPair::getCourse, 
           mapping(CourseStundentPair::getStudent, toList()) 
        ) 
      ); 

     for (Course course :courseToStudents.keySet()){ 
      System.out.printf("Course %s , Students: %s \n" 
        ,course.getName() 
        ,courseToStudents.get(course).stream().map(Student::getName) 
            .collect(joining(", "))); 
     } 

    } 

控制檯將輸出

Course English , Students: Student1, Student2, Student3 
Course Literature , Students: Student1 
Course Mathematics , Students: Student1, Student2 

注意,在Eclipse IDE中可能會抱怨編譯錯誤,在它的IntelliJ會正常工作。