0

I have a Student object as below

class Student{
    String name,email,country;
    //getters setters
}

And I need collect the elements as TreeMap<String,List<String>> where key is student's country and value is the list of email

Map<String, List<Student>> countryStudents = students.stream()
            .collect(Collectors.groupingBy(Student::getCountry));
Map<String,List<String>> map = new HashMap<>();
        countryStudents .entrySet().forEach(entry -> map.put(entry.getKey(),entry.getValue().stream().map(student -> student .getEmail()).collect(Collectors.toList())));

Am wondering if is there any efficient way to do this instead of doing it in 2 iterations.

OTUser
  • 3,788
  • 19
  • 69
  • 127

1 Answers1

3

You can use groupingBy collector along with mapping collector to do it in one pass. Here's how it looks.

Map<String, List<String>> map = students.stream()
    .collect(Collectors.groupingBy(Student::getCountry, TreeMap::new, 
        Collectors.mapping(Student::getEmail, Collectors.toList())));

Alternatively, a much better approach is to use computeIfAbsent to construct the map in single pass over the list. If I were you, I would rather use this.

Map<String, List<String>> stdMap = new TreeMap<>();
for (Student student : students) 
    stdMap.computeIfAbsent(student.getCountry(), unused -> new ArrayList<>())
        .add(student.getEmail());
Ravindra Ranwala
  • 20,744
  • 6
  • 45
  • 63