Java 8, Lambda: Sorting within grouped Lists and merging all groups to a list

后端 未结 9 1313
难免孤独
难免孤独 2021-02-09 04:21

Based on the following answer: https://stackoverflow.com/a/30202075/8760211

How to sort each group by stud_id and then return a List with all Students as result of the g

9条回答
  •  悲&欢浪女
    2021-02-09 04:38

    Since the result is supposed to be a list, you‘re not grouping but simply sorting (in the sense of changing the order according to a defined rule). The main obstacle is that you want the locations to be ordered after their first encounter in the original list.

    The straight-forward approach is to fix this location order first, followed by a single sort operation:

    Map locationOrder = studlist.stream()
        .collect(HashMap::new,
                 (m,s)->m.putIfAbsent(s.stud_location, m.size()),
                 (m1,m2)->m2.keySet().forEach(l->m1.putIfAbsent(l, m1.size())));
    
    studlist.sort(Comparator.comparingInt((Student s) -> locationOrder.get(s.stud_location))
                            .thenComparing(s -> s.stud_id));
    

    If you can not or do not want to modify the original list, you can simply use a copy:

    List result = new ArrayList<>(studlist);
    result.sort(Comparator.comparingInt((Student s) -> locationOrder.get(s.stud_location))
                          .thenComparing(s -> s.stud_id));
    

    It’s also possible to solve this with a grouping operation, but that’s not easier:

    List result = studlist.stream()
        .collect(Collectors.collectingAndThen(
                    Collectors.groupingBy(s -> s.stud_location,
                                          LinkedHashMap::new, Collectors.toList()),
                    m -> m.values().stream()
                          .flatMap(l -> l.stream().sorted(Comparator.comparing(s->s.stud_id)))
                          .collect(Collectors.toList())));
    

    Note that you have to collect into a LinkedHashMap to ensure that the order of the groups is retained.

提交回复
热议问题