Using groupingby with java streams

332 Views Asked by At

I have a list of students, refer to the DTO.

I am trying to derive the result of the section and session. For example: We have a collection of students with varying section & sessions:

Students:
[Student [id=1, section=section-a, result=pass, session=2020],
Student [id=2, section=section-a, result=failed, session=2020], 
Student [id=1, section=section-b, result=passed, session=2020]]

Now I have to derive the overall result taking section & session into consideration.

So for the above data, we should see: section-a, session:2020 has failed, because we have one failed student. Similarly, for the second group i.e section-b, session:2020, the result should be passed, because we have only 1 student, that too with the passed result.


class Student {
private String id;
private String section;
private String result;
private String session;

public String getId() {
    return id;
}

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

public String getSection() {
    return section;
}

public void setSection(String section) {
    this.section = section;
}

public String getResult() {
    return result;
}

public void setResult(String result) {
    this.result = result;
}

public String getSession() {
    return session;
}

public void setSession(String session) {
    this.session = session;
}

@Override
public String toString() {
    return "Student [id=" + id + ", section=" + section + ", result=" + result + ", session=" + session + "]";
}

}

Main classs

public class GroupingBy {

public static void main(String[] args) {
    System.out.println("Hello world!");

    List<Student> students = new ArrayList<>();
    Student student = new Student();
    student.setId("1");
    student.setResult("pass");
    student.setSection("section-a");
    student.setSession("2020");

    Student student1 = new Student();
    student1.setId("2");
    student1.setResult("failed");
    student1.setSection("section-a");
    student.setSession("2020");

    Student student2 = new Student();
    student2.setId("1");
    student2.setResult("failed");
    student2.setSection("section-b");
    student.setSession("2020");

    students.add(student);
    students.add(student1);
    students.add(student2);

    System.out.println("Students:" + students);
}

}

I thought of using java streams and perform groupby operation so that I can get something like this:

{section-a,2020 = passed:1, failed:1},{section-b,2020 = passed:1}

and then I can use the above data to derive the final result. I tried that but seems like key cannot be a combination. Or is there another way to achieve this?

Please help

1

There are 1 best solutions below

1
On

You can first group by Section and Session using Collectors.groupingBy then again group by Result and use Collectors.counting() to count the size of the group.

Map<SimpleEntry<String, String>, Map<String, Long>> map = 
        students.stream()
                    .collect(Collectors.groupingBy(
                                    e -> new AbstractMap.SimpleEntry<>(e.getSection(), e.getSession()),
                                Collectors.groupingBy(e -> e.getResult(), Collectors.counting())));