Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

filter a list of object by its list field

There are two plain objects for Student and Course like this:

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

If we have a list of Students, how can we filter some of students by the name of their courses?

  • first I try flatMap to answer this question, but it returns course objects instead student objects.
  • then I use allMatch (following codes). however it returns Student list but the List always is empty. What is the problem?
List<Student> studentList;
List<Student> AlgorithmsCourserStudentList = studentList.stream().
    filter(a -> a.stream().allMatch(c -> c.getCourseName.equal("Algorithms"))).
    collect(Collectors.toList());
like image 343
MohsenIT Avatar asked Nov 20 '25 09:11

MohsenIT


2 Answers

You need anyMatch:

List<Student> studentList;
List<Student> algorithmsCourseStudentList = 
    studentList.stream()
               .filter(a -> a.getCourses()
                             .stream()
                             .anyMatch(c -> c.getCourseName().equals("Algorithms")))
               .collect(Collectors.toList());
  • allMatch will only give you Students that all their Courses are named "Algorithms".

  • anyMatch will give you all Students that have at least one Course named "Algorithms".

like image 146
Eran Avatar answered Nov 22 '25 22:11

Eran


For each student get the courses and find if there is any match in the student's courses on the name of the course.

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());
  • Your code here won't compile, in the filter 'a' is a student, which is does not have a stream() method.
  • You can't use flatMap() to convert the student's list of courses to a stream because then you can't collect the students further on
  • allMatch yields true if all elements in the list match the predicate, false if there is a single element not matching. So if the code would be correct you'd be testing if all the student's courses have the name 'Algorithms', but you want to test if there is a single element that matches the condition. Note that allMatch and anyMatch do not return lists, they return a boolean which is why you can use them in the filter.
like image 20
M. le Rutte Avatar answered Nov 22 '25 23:11

M. le Rutte



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!