按列表字段过滤对象列表

时间:2017-10-08 14:05:46

标签: java lambda collections java-8 java-stream

学生和课程有两个普通对象:

public class Student {
    List<Course> courses;
    ...
}
public class Course {
    String name;
    ...
}

如果我们有list Students,我们如何根据课程名称过滤一些学生?

  • 首先我尝试flatMap回答这个问题,但它会返回课程 对象而不是学生对象。
  • 然后我使用allMatch(以下代码)。 但它会返回学生列表,但List始终为空。是什么 问题?
List<Student> studentList;
List<Student> AlgorithmsCourserStudentList = studentList.stream().
    filter(a -> a.stream().allMatch(c -> c.getCourseName.equal("Algorithms"))).
    collect(Collectors.toList());

3 个答案:

答案 0 :(得分:7)

您需要anyMatch

List<Student> studentList;
List<Student> algorithmsCourseStudentList = 
    studentList.stream()
               .filter(a -> a.getCourses()
                             .stream()
                             .anyMatch(c -> c.getCourseName().equals("Algorithms")))
               .collect(Collectors.toList());
  • allMatch只会向您Student提供所有Course名为"Algorithms"的内容。

  • anyMatch将为您提供至少有一个Student名为Course的{​​{1}}。

答案 1 :(得分:2)

每位学生都可以参加课程,并找到学生课程名称中是否有匹配。

Course.java:

public class Course {
    private String name;

    public String getName() {
        return name;
    }
}

Student.java:

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

public class Student {
    private List<Course> courses;

    public List<Course> getCourses() {
        return courses;
    }

    public static void main(String... args) {
        List<Student> students = new ArrayList<>();

        List<Student> algorithmsStudents = students.stream()
                .filter(s -> s.getCourses().stream().anyMatch(c -> c.getName().equals("Algorithms")))
                .collect(Collectors.toList());
    }
}

编辑:

List<Student> AlgorithmsCourserStudentList = studentList.stream().
    filter(a -> a.stream().allMatch(c -> c.getCourseName.equal("Algorithms"))).
    collect(Collectors.toList());
  • 您的代码在这里不会编译,在过滤器&#39; a&#39;是学生,没有stream()方法。
  • 您不能使用flatMap()将学生的课程列表转换为流,因为这样您就无法进一步收集学生
  • 如果列表中的所有元素与谓词匹配,则
  • allMatch会产生true,如果单个元素不匹配,则false。因此,如果代码是正确的,您将测试所有学生的课程是否具有“算法”的名称,但您想测试是否存在与该条件匹配的单个元素。请注意,allMatchanyMatch 不会返回列表,它们会返回boolean,这就是您可以在过滤器中使用它们的原因。

答案 2 :(得分:1)

我同意@Eran。您也可以在method references中使用filter,如下所示:

students.stream()
            .filter(s -> s.getCourses().stream()
                    .map(Course::getName)
                    .anyMatch("Algorithms"::equals)
            ).collect(Collectors.toList());