最近有人问了一个问题,归结为对于给定的哈希表,Map<Person, AtomicInteger>需要从Person最大值为 的键中找到名称AtomicInteger / Integer。
该解决方案显示了使用 查找单个最大值的示例,以及使用普通哈希表迭代查找可以具有相同最大值Stream::max(Comparator<? super T> cmp)的名称列表的示例:
record Result(Integer max, List<String> names) {}
public static Result getNamesWithMaxValue(Map<Person, AtomicInteger> map) {
int max = Integer.MIN_VALUE;
List<String> names = new ArrayList<>();
for (Map.Entry<Person, AtomicInteger> e : map.entrySet()) {
int curr = e.getValue().get();
if (curr >= max) {
if (curr > max) {
max = curr;
names.clear();
}
names.add(e.getKey().getName());
}
}
return new Result(max, names);
}
问题来了,如何使用 Stream API 获取所有最大值(或最小值)的列表,以及与常规循环相比,这种解决方案的效率如何?希望该解决方案是通用的,而不是针对上述问题的特定情况。
有几种可能的解决方案:
Collector.of(Supplier<A> supplier, BiConsumer<A,T> accumulator, BinaryOperator<A> combiner, Function<A,R> finisher)Supplier<A>accumulatorcombinerfinisherList<T>List<R>在这种情况下,我们得到了双重传递(在最坏的情况下)——首先遍历输入集合,然后遍历一组组——然后为这些组生成中间列表。
要搜索最小值,您应该
Stream::min在第一个变体中使用,在第二个变体中,将比较符号从“更多”更改为“更少”。同样,如果除了结果列表之外你还想获得最大值,如原题,你可以实现一个包装类并添加另一个转换器函数,将输入集合中的数据转换为所需的结果:
在带有自定义收集器的版本中,它略有修改
finisher:在带有分组的变体中,结果被修改(或者你可以返回
Map.Entry):测试:
对于空输入集合:
主要 SO 上的类似问题:
跟进@NowhereMan 的回答。
您可以为以下产品制作定制电池
Stream.reduce:然后可以这样写一个将人映射到整数的示例:
结果: