如何使用Java Streams从对象列表中获取Set

时间:2018-12-17 13:27:24

标签: java collections java-8 java-stream

这可能是一个简单的Java流问题。说,我有一个List<Student>对象。

public class Student {
    public String name;
    public Set<String> subjects;

    public Set<String> getSubjects() {
        return subjects;
    }
}

如何获取学生名单上的所有科目?

我可以为每个循环使用a。如何转换以下代码以使用流?

for (Student student : students) {
    subjectsTaken.addAll(student.getSubjects());
}

这是我尝试使用Java 8流的尝试。这给我一个Incompatible types错误。

Set<String> subjectsTaken = students.stream()
        .map(student -> student.getSubjects())
        .collect(Collectors.toSet());

3 个答案:

答案 0 :(得分:5)

您当前的代码产生一个Set<Set<String>>,而不是Set<String>

您应该使用flatMap,而不是map

Set<String> subjectsTaken = 
    students.stream() // Stream<Student>
           .flatMap(student -> student.getSubjects().stream()) // Stream<String>
           .collect(Collectors.toSet()); // Set<String>

答案 1 :(得分:4)

尝试一下:

Set<String> subjectsTaken = 
                   students.stream()
                           .map(Student::getSubjects)
                           .flatMap(Set::stream) 
                           .collect(Collectors.toSet());

想法是首先将学生映射到他们的主题,然后将Stream<Set<String>>展平到Stream<String>,最后将流收集到Set


我建议您在可能的情况下(如果不降低可读性)使用方法引用而不是 lambda表达式

答案 2 :(得分:1)

使用Stream<T>#<R>collect的另一种选择:

students.stream()
    .map(Student::getSubjects)
    .<Set<String>>collect(HashSet::new, Collection::addAll, Collection::addAll)