Java Stream:查找具有属性最小值/最大值的元素

新手上路,请多包涵

我有一个对象流,我想找到一个具有计算成本高的某些属性的最大值的对象。

作为一个具体的简单示例,假设我们有一个字符串列表,我们想找到最酷的字符串,给定一个 coolnessIndex 函数。

以下应该工作:

 String coolestString = stringList
        .stream()
        .max((s1, s2) -> Integer.compare(coolnessIndex(s1), coolnessIndex(s2)))
        .orElse(null);

现在,这有两个问题。首先,假设 coolnessIndex 的计算成本很高,这可能不会很有效。我想 max 方法将需要重复使用比较器,这反过来将调用 coolnessIndex 重复,最后它将为每个字符串调用多次。

其次,必须提供比较器会导致代码中出现一些冗余。我更喜欢这样的语法:

 String coolestString = stringList
        .stream()
        .maxByAttribute(s -> coolnessIndex(s))
        .orElse(null);

但是,我一直未能在 Stream API中找到匹配的方法。这让我感到惊讶,因为通过属性查找最小值/最大值似乎是一种常见模式。我想知道是否有比使用比较器更好的方法(除了 for 循环)。

原文由 Jan Pomikálek 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 1.6k
2 个回答

谢谢大家的建议。最后我在 Efficiency of the way comparator works 找到了我最喜欢的解决方案——来自 bayou.io 的答案:

有一个通用的 cache 方法:

 public static <K,V> Function<K,V> cache(Function<K,V> f, Map<K,V> cache)
{
    return k -> cache.computeIfAbsent(k, f);
}

public static <K,V> Function<K,V> cache(Function<K,V> f)
{
    return cache(f, new IdentityHashMap<>());
}

然后可以按如下方式使用:

 String coolestString = stringList
        .stream()
        .max(Comparator.comparing(cache(CoolUtil::coolnessIndex)))
        .orElse(null);

原文由 Jan Pomikálek 发布,翻译遵循 CC BY-SA 3.0 许可协议

Stream<String> stringStream = stringList.stream();
String coolest = stringStream.reduce((a,b)->
    coolnessIndex(a) > coolnessIndex(b) ? a:b;
).get()

如果调用 coolnessIndex 很昂贵,我们可以使用 distinct 所以它只针对不同的元素调用(假设 coolnesIndex 对于相同的元素是相同的)

 Stream<String> stringStream = stringList.stream().distinct();
String coolest = stringStream.reduce((a,b)->
    coolnessIndex(a) > coolnessIndex(b) ? a:b;
).get()

流不同()

原文由 frhack 发布,翻译遵循 CC BY-SA 4.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题