使用groupingBy与Collectors.maxBy时解开Optional包装。

huangapple go评论68阅读模式
英文:

Unwrap Optional when using Collectors maxBy with groupingBy

问题

以下是翻译好的内容:

我有一个带有`String``int`字段的类

    public class Data {
        private String name;
        private int value;

        private Data(String name, int value) {
            this.name = name;
            this.value = value;
        }

        public String getName() {
            return name;
        }

        public int getValue() {
            return value;
        }
    }

我有一个`List<Data>`,如果我想创建一个地图分组),以了解每个*名称**最大值*的数据对象我可以这样做

    Map<String, Optional<Data>> result = list.stream()
                .collect(Collectors.groupingBy(Data::getName,
                        Collectors.maxBy(Comparator.comparing(Data::getValue))));

但是由于`Collectors.maxBy`的合同RHS被包装在Optional中但我想要一个`Map<String, Data>`。

我能想到的一个选项是使用`Collectors.collectingAndThen`,但我将不得不创建一个不必要的中间地图

    list.stream()
             .collect(Collectors.collectingAndThen(Collectors.groupingBy(Data::getName,
                    Collectors.maxBy(Comparator.comparing(Data::getValue))),
                    map -> map.entrySet().stream()
                            .collect(Collectors.toMap(Map.Entry::getKey,
                                     e -> e.getValue().get()))));

是否有一种使用流来实现这个的成熟方式
英文:

I have a class with a String and an int field.

public class Data {
private String name;
private int value;
private Data(String name, int value) {
this.name = name;
this.value = value;
}
public String getName() {
return name;
}
public int getValue() {
return value;
}
}

I have a List<Data> and if I want to create a map (grouping) to know the Data object with maximum value for each name, I could do like,

Map<String, Optional<Data>> result = list.stream()
.collect(Collectors.groupingBy(Data::getName,
Collectors.maxBy(Comparator.comparing(Data::getValue))));

But, the RHS is wrapped in an Optional because of the contract of Collectors.maxBy but I want a Map<String, Data>.

One option I could think of it to use Collectors.collectingAndThen, but I will have to create an unnecessary intermediate map.

list.stream()
.collect(Collectors.collectingAndThen(Collectors.groupingBy(Data::getName,
Collectors.maxBy(Comparator.comparing(Data::getValue))),
map -> map.entrySet().stream()
.collect(Collectors.toMap(Map.Entry::getKey,
e -> e.getValue().get()))));

Is there an idiomatic way to achieve this using streams?

答案1

得分: 11

你可以使用 BinaryOperator.maxBy 结合 Collectors.toMap

Map<String, Data> result = list.stream()
        .collect(Collectors.toMap(Data::getName, Function.identity(),
            BinaryOperator.maxBy(Comparator.comparing(Data::getValue))));
英文:

You can use BinaryOperator.maxBy with Collectors.toMap

Map&lt;String, Data&gt; result = list.stream()
.collect(Collectors.toMap(Data::getName, Function.identity(),
BinaryOperator.maxBy(Comparator.comparing(Data::getValue))));

huangapple
  • 本文由 发表于 2020年7月30日 01:35:00
  • 转载请务必保留本文链接:https://go.coder-hub.com/63159338.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定