【问题标题】:Streams versus collections流与集合
【发布时间】:2018-07-27 15:57:24
【问题描述】:

我有一个玩家列表,想要获得最低评分的玩家。我可以这样做:

Player player1 = Collections.min(players,Comparator.comparing(Player::getRating));

或者我可以这样做:

Player player2 = players.stream().min(Comparator.comparing(Player::getRating)).get();

在性能方面或其他方面哪个更好?

【问题讨论】:

  • 做一个基准测试看看。
  • 没有魔法。两种方法都遍历所有元素并进行比较。
  • @Holger 如果流理论上可以注册它已经按某个属性排序,如TreeSet<>(Comparator.comparing) 等,只是理论上
  • @Aomine 你删除了é?无论如何,我认为理论上如果蒸汽已排序并且这是在流管道上注册的标志,您可以简单地返回第一个或最后一个条目而不遍历源
  • 我考虑了一段时间,最终决定简化一些事情并将其保留为 e 而不是 é

标签: java collections java-8 java-stream


【解决方案1】:

应该不会有太大的不同。
我们可以争辩说流方式可以利用并行流选项,而Collections.min() 不能。
在您提出的两种情况下,拳击都可能需要大量费用。所以你应该支持comparingInt()/comparingDouble()/comparingLong()comparing()

【讨论】:

  • 流变体还为您提供了更多选项,用于在“无价值”情况下做什么,因为对min 的调用返回Optional<T>。而Collections.min 只会在集合为空时抛出异常。
  • @Eugene 对于已经排序的东西来说,这确实是一个有趣的点。
  • @Aomine 这是一个有趣的观点,但在实际应用中,我会根据上下文偏爱其中一个或第二个。有时您正在寻找容错,因为您操作的内容需要它。在其他情况下,您不想要这种容忍度,因为在功能上它不被接受。因此,使用 Optional 之类的东西并处理不可能发生的情况可能会被阅读代码的人视为死代码或“令人惊讶”的代码。
【解决方案2】:

鉴于您的问题是“在性能方面或其他方面哪个更好?” @davidxxx 和 @Eugene 已经阐述了一些有趣的观点,这里还有一个:

支持流变体的另一个原因是,对min 的调用返回一个Optional<T>,它本身就足够具有描述性,并且还使用户能够决定在“无价值”情况下要做什么,而Collections.min如果集合为空,则只会抛出异常,这也可能是用户想要的,但这是需要考虑的事情。我个人的偏好是流版本,因为它在“无价值”情况下为您提供了更多选择。

也就是说,如果您不需要那些额外的选项,仅仅是因为 总是 是一个最小值或者一个异常足够有意义,那么我会采用第一种方法。

最终,您决定继续使用的选项不应取决于性能,因为它们之间没有太大差异,除非另有说明,否则您相信您可以利用并行流 API。

相反,在这种特定情况下,我建议您考虑我上面提到的内容,并采用对您和/或您的同事更易读/更舒适的方法。

【讨论】:

    【解决方案3】:

    好吧,如果传入的源已经排序,Stream 实现可能只返回来自该源的第一个(或最后一个)条目,而不像Collections.min 那样遍历整个Collection。对于您的示例,这可能看起来太复杂了,但对于更简单的事情可能会更容易。

    目前尚未完成,但将来可能会实施,因此我可以支持stream 可能。

    【讨论】:

    • +1。此外,支持流变体的另一个原因是,对min 的调用返回一个Optional<T>,它本身就具有足够的描述性,并且还使用户能够决定在“无价值”情况下要做什么,而Collections.min 会如果集合为空,只需抛出一个异常,这也可能是用户想要的,但这是需要考虑的事情。我个人的偏好是流版本,因为它在“无价值”情况下为您提供了更多选择。
    猜你喜欢
    • 1970-01-01
    • 2017-02-17
    • 2015-06-29
    • 2014-05-04
    • 1970-01-01
    • 1970-01-01
    • 2016-11-02
    • 1970-01-01
    • 2022-08-22
    相关资源
    最近更新 更多