使用流对 AbstractMap 的三个最大数字求和

Summing three biggest numbers of an AbstractMap using streams

我有一个问题。如何计算这个结构的三个最大最大值?

public static AbstractMap.SimpleEntry<String, Long> sum3max(List<AbstractMap.SimpleEntry<String, Long>> list){... }

预期输出应如下所示:

List<AbstractMap.SimpleEntry<String, Long>> list = new ArrayList<>(); 

list.add(new AbstractMap.SimpleEntry<>("apple", 20L));  
list.add(new AbstractMap.SimpleEntry<>("tomato", 30L)); 
list.add(new AbstractMap.SimpleEntry<>("apple", 10L)); 
list.add(new AbstractMap.SimpleEntry<>("tomato", 20L)); 
list.add(new AbstractMap.SimpleEntry<>("tomato", 10L)); 
list.add(new AbstractMap.SimpleEntry<>("tomato", 40L));
list.add(new AbstractMap.SimpleEntry<>("apple", 60L));
list.add(new AbstractMap.SimpleEntry<>("apple", 5L));
// apple = 90 because we are counting 60+20+10 (three biggest numbers of all apples)
// tomato = 90 because 30+20+40 (three biggest numbers of all tomatos )

System.out.println(sum3max(list)); // should be   apple=90, because 'a' in apple is alphabetically smaller than 't' in tomato

你能帮帮我吗?我试过这样的东西,但它只适用于对所有值求和,而不仅仅是三个最大的值。

var map = list.stream().collect(Collectors.groupingBy(AbstractMap.SimpleEntry::getKey,Collectors.summingLong(AbstractMap.SimpleEntry::getValue)));
Map.Entry<String, Long> maxEntry = map.entrySet().stream()
                .max(Map.Entry.comparingByValue()).get();


        return new AbstractMap.SimpleEntry<>(maxEntry.getKey(), maxEntry.getValue());

这是一种流式传输值的方法。 首先,创建一个 lambda 作为 finisher 来对列表中最大的 3 个值求和。后面会用到。

终结者

  • finisher 拿了一个 long 的列表,returns 一个 long
  • 首先将值倒序排列
  • 限制为 3 或更少并映射到长
  • 然后将它们相加 return 总和
Function<List<Long>, Long> sum =
        lst -> lst.stream().sorted(Comparator.reverseOrder())
                .limit(3).mapToLong(Long::longValue).sum();

流式传输条目

  • 流式传输条目列表。
  • fruitvalue list of longs 键控的项目分组
    • longs 需要通过 Collectors.mapping 从他们的条目中提取。
    • 然后使用collectingAndThen首先将这些多头收集到列表中
    • 后面是前面定义的finisher到return的长和
Map<String,Long> map =
        list.stream()
           .collect(Collectors.groupingBy(Entry::getKey,
                Collectors.mapping(Entry::getValue,
                    Collectors.collectingAndThen(
                            Collectors.toList(),
                                        sum::apply))));

 map.entrySet().forEach(System.out::println);

打印

apple=90
tomato=90

我的解决方案允许少于三个数字的项目。也可以过滤掉此类列表。我选择允许他们。