How to filter data from nested list using Stream Java 8

In this post, we will see how to filter data from nested list using Stream Java 8.

Consider the use case, we have List of Student. The Student class contains id, name and List<Subject> fileds. Inside Subject we have two fields subjectName and score.

We want to get id and name of Student that belongs to subjectName Math and get score 100.

For the above use case, first we will get all list of students using anyMatch(). Futher using forEach() we can get id and name of Student. We can also use the Stream flatMap() method.

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

class Student {
    private String name;
    private int id;
    private List<Subject> subjects;
    
    public Student(String name, int id, List<Subject> subjects) {
        this.name = name;
        this.id = id;
        this.subjects = subjects;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public List<Subject> getSubjects() {
        return subjects;
    }

    public void setSubjects(List<Subject> subjects) {
        this.subjects = subjects;
    }

    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", id=" + id +
                ", subjects=" + subjects +
                '}';
    }
}

class Subject {
    private String subjectName;
    private int score;

    public Subject(String subjectName, int score) {
        this.subjectName = subjectName;
        this.score = score;
    }


    public String getSubjectName() {
        return subjectName;
    }

    public void setSubjectName(String subjectName) {
        this.subjectName = subjectName;
    }

    public int getScore() {
        return score;
    }

    public void setScore(int score) {
        this.score = score;
    }

    @Override
    public String toString() {
        return "Subject{" +
                "subjectName='" + subjectName + '\'' +
                ", score=" + score +
                '}';
    }
}

public class Test {
    public static void main(String[] args) {

        List<Student> students = new ArrayList<>();

        Subject subject1 = new Subject("Math", 100);
        Subject subject2 = new Subject("Hindi", 120);
        Subject subject3 = new Subject("English", 130);

        List<Subject> subjects = new ArrayList<>();
        subjects.add(subject1);
        subjects.add(subject2);
        subjects.add(subject3);

        Student student = new Student("Rakesh", 10, subjects);
        students.add(student);

        List<Student> studentList = students.stream().
                filter(student1 -> student1.getSubjects().stream().anyMatch(subject -> subject.getSubjectName().equals("Math") &&
                        subject.getScore() == 100)).collect(Collectors.toList());


        studentList.forEach(student1 ->
                System.out.println(student1.getName() + "   " + student1.getId())
        );
        //Without using Java 8
/*        for (Student student1 : students) {

            for (Subject subject4 : student1.getSubjects()) {
                if (subject4.getSubjectName().equals("Math") && subject4.getScore() == 100) {
                    System.out.println("Id is  " + student1.getId() + "Name is " + student1.getName());
                    break;
                }
            }
        }*/
    }
}

Output:-

Rakesh   10

We can also use the Stream flatMap() method.

        // Use flatMap to flatten the stream of subjects
        students.stream()
                .flatMap(s -> s.getSubjects().stream()) // Flatten subjects
                .filter(subject -> "Math".equals(subject.getSubjectName()) && subject.getScore() == 100)
                .forEach(subject -> {
                    System.out.println("Student ID: " + student.getId());
                    System.out.println("Student Name: " + student.getName());
                });

Summary – We have seen How to filter data from nested list using Stream Java 8.

Reference

https://docs.oracle.com/javase/8/docs/api/