10

Say I have a list of objects called Student. Object Student is defined like so

public Class Student {
    private String studentName;
    private String courseTaking;
}

In the list of students, there can be multiple student objects with the same studentName but different courseTaking. Now I want to turn the list of students into a map of studentName and courseTaking like so

Map<String, Set<String>>

The key is studentName, and the value is all of the courseTaking of the same student put together as a set. How can I do this using stream() & collect()?

shmosel
  • 49,289
  • 6
  • 73
  • 138
Zoff
  • 317
  • 3
  • 9
  • When you ask how to do it "using lambda expressions", do you actually mean to ask how to do it using Streams? Because it can be done with Streams and method references *(assuming getter methods exist)*, without any lambda expressions, so the question to you would be why it has to use lambda expressions? – Andreas Sep 19 '17 at 22:41
  • Yeah I did mean to use stream(). Sorry for not being clear in the first draft. I can turn the list into a map of list using groupBy(), but I can't figure out how to turn that into a map of set. – Zoff Sep 19 '17 at 22:48
  • So you have repeated `Student` objects for each course the student is taking ? Definitely doesn't feel right. The courses should be an array in the `Student` object directly. – Isac Sep 19 '17 at 22:48
  • 2
    `students.stream().collect(groupingBy(Student::getStudentName, mapping(Student::getCourseTaking, toSet())))` – shmosel Sep 19 '17 at 22:49

1 Answers1

10

I think this is what you're looking for:

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


public class StackOverflow {

  private static class SO46310655 {
    public static void main(String[] args) {
      final List<Student> students = new ArrayList<>();
      students.add(new Student("Zoff", "Java 101"));
      students.add(new Student("Zoff", "CompSci 104"));
      students.add(new Student("Zoff", "Lit 110"));
      students.add(new Student("Andreas", "Kotlin 205"));
      Map<String, Set<String>> map = students.stream().collect(
          Collectors.groupingBy(
              Student::getStudentName,
              Collectors.mapping(
                  Student::getCourseTaking,
                  Collectors.toSet()
              )
          )
      );
      System.out.println(map);
    }

    public static class Student {
      private final String studentName;
      private final String courseTaking;

      public Student(String studentName, String courseTaking) {
        this.studentName = studentName;
        this.courseTaking = courseTaking;
      }

      public String getStudentName() {
        return studentName;
      }

      public String getCourseTaking() {
        return courseTaking;
      }
    }
  }
}

yeilds {Andreas=[Kotlin 205], Zoff=[Java 101, CompSci 104, Lit 110]}

Andreas
  • 4,937
  • 2
  • 25
  • 35