代码之家  ›  专栏  ›  技术社区  ›  SyncMaster

如何使用Java流从对象列表中获取集合

  •  4
  • SyncMaster  · 技术社区  · 6 年前

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

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

    我怎样才能把所有的科目都列在学生名单上?

    我可以使用for each循环来完成这个操作。如何将下面的代码转换为使用流?

    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 回复  |  直到 6 年前
        1
  •  5
  •   Eran    6 年前

    当前代码生成 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>
    
        2
  •  4
  •   ETO    6 年前

    试试这个:

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

    这个想法是先把学生画到他们的科目上,然后把 Stream<Set<String>> Stream<String> 最后收集到一条小溪 Set .


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

        3
  •  1
  •   HPH    6 年前

    另一种选择是使用 Stream<T>#<R>collect 以下内容:

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