按照其列表字段过滤对象列表

3
有两个类似于这样的普通对象,分别是学生(Student)和课程(Course):
public class Student {
    List<Course> courses;
    ...
}
public class Course {
    String name;
    ...
}

如果我们有一个学生列表(list of Students),如何通过他们课程的名称来筛选一些学生?

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

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 的课程都被命名为 "Algorithms" 的结果。

  • anyMatch 会返回至少有一个课程被命名为 "Algorithms" 的所有 Student 的结果。


3

针对每个学生获取课程,并查找在学生的课程中是否有与课程名称匹配的课程。

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());
    }
}

edit:

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

你在已经有人回答了10分钟后才发布了一个回答,而且你的回答质量比之前的回答低,因为你的回答只是简单地倾倒了一些代码,而他的回答则提供了解释。 - Hovercraft Full Of Eels
不好意思,另一个答案是错误的,我正在回答这个问题时它被编辑了。 - M. le Rutte

1

我同意 @Eran 的观点。此外,您可以在 filter 中使用以下的 方法引用

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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接