简体   繁体   中英

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??

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 Course s, 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.

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));
    });

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM