从 lambda 表达式进行排序和子列表

2022-09-03 05:03:59

我有一个包含以下元素的数组列表:

List<Record> list = new ArrayList<>();
list.add(new Record(3, "32"));
list.add(new Record(4, "42"));
list.add(new Record(1, "12"));
list.add(new Record(1, "11"));
list.add(new Record(2, "22"));
list.add(new Record(5, "52"));
list.add(new Record(5, "53"));
list.add(new Record(5, "51"));

记录是一个简单的 POJO,具有 ID 和名称

我想对列表做这些。

  • 创建一个像这样的地图,有一个键是id和更苗条的键添加为列表。我已经这样做了。Map<Integer, List<Record>>

    Map<Integer, List<Record>> map = list.stream()
        .collect(Collectors.groupingBy(Record::getId, HashMap::new, Collectors.toList()));
    
  • 现在我想按名称对列表进行排序,并在地图内提供限制

    map.forEach((k, v) -> v.stream().sorted(Comparator.comparing(Record::getName)));    
    map.forEach((k, v) -> map.put(k, v.subList(0, Math.min(**limit**, v.size()))));
    

我已经像上面一样尝试过,看起来这不是一个好方法。任何人都可以建议更好的方法吗?


答案 1

您可以使用 Java 8 Collectors.collectingAndThen() 方法:

Map<Integer, List<Record>> map = list.stream()
    .collect(Collectors.groupingBy(
        Record::getId,
        Collectors.collectingAndThen(
            Collectors.toList(),
            records -> records.stream()
                              .sorted(Comparator.comparing(Record::getName))
                              .limit(limit)
                              .collect(Collectors.toList()))));

答案 2

您可以使用 :Collectors.collectingAndThen

Map<Integer, List<Record>> result = list.stream()
    .collect(Collectors.groupingBy(
         Record::getId,
         Collectors.collectingAndThen(
             Collectors.toCollection(ArrayList::new),
             v -> {
                 v.sort(Comparator.comparing(Record::getName));
                 return v.subList(0, Math.min(LIMIT, v.size()));
             })));

此解决方案可避免为每个列表组创建新流。

正如本答案中所指出的,通过使用,我们确保列表是可变的,以便我们以后可以对其进行适当的排序。Collectors.toCollection(ArrayList::new)


推荐