Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to limit in groupBy java stream

This is my course model in class named Course:

public class Course{
    private int courseId;
    private String courseName;
    private Teacher teacher;
}

This is my teacher model in class named Teacher:

public class Teacher{
    private int teacherId;
    private String name;
}

I want to get a Map<String, List<Course>> but if the teacherId is repeated just add that Course into list of map.

I am using groupBy for it

Map<Integer, List<Course>>  result = courses.stream()
        .collect(Collectors.groupingBy(c -> c.getTeacher().getTeacherId(), Collectors.toList()));

and it's giving result as expected.

But I want to limit here that As soon as 5 teachers are found stop to process and returned the result.

How can it be done??

like image 917
Iti Gupta Avatar asked Feb 05 '18 11:02

Iti Gupta


2 Answers

There’s no direct support for this, as stopping and living with potentially incomplete data is rather unusual.

A straight-forward solution collecting the first five groups completely, would be

Set<Integer> firstFive = courses.stream()
    .map(c -> c.getTeacher().getTeacherId())
    .distinct().limit(5)
    .collect(Collectors.toSet());
Map<Integer, List<Course>> result = courses.stream()
    .filter(c -> firstFive.contains(c.getTeacher().getTeacherId()))
    .collect(Collectors.groupingBy(c -> c.getTeacher().getTeacherId()));

Here, the Course lists of these first five teacher ids are complete.


A solution that truly stops after encountering the 5th teacher id, would be simpler with a loop:

Map<Integer, List<Course>> result = new HashMap<>();
for(Course c: courses) {
    result.computeIfAbsent(c.getTeacher().getTeacherId(), x -> new ArrayList<>()).add(c);
    if(result.size() == 5) break;
}

But there is not much sense in collecting lists of Courses, when you can’t trust these lists afterwards. Keep in mind, that even the source list’s very last element could belong to the first encountered teacher ID, so you need to process the entire list even if you are interested in only one teacher’s complete list of courses.

like image 112
Holger Avatar answered Nov 15 '22 17:11

Holger


Not sure if this is what you are asking.

Map<Integer, List<Course>> map = new HashMap<>();

courses.stream().filter(course -> map.keySet().size() < 10)
    .forEach(entry -> {
       // The code below can be simplified
      int teacherId = entry.getTeacher().getTeacherId();
      if(map.get(teacherId) != null)
        map.get(teacherId).add(entry);
      else
        map.put(teacherId, Lists.newArrayList(entry));
    });
like image 31
pvpkiran Avatar answered Nov 15 '22 18:11

pvpkiran