【问题标题】:Java Stream API's Collectors.toList() and Collectors.toSet() mechanicsJava Stream API 的 Collectors.toList() 和 Collectors.toSet() 机制
【发布时间】:2022-01-08 07:39:49
【问题描述】:

如果我有 HashSet 并且我使用流 .filter() 进行某些操作然后执行 .collect(Collectors.toList()) 与仅将流收集回 HashSet .collect(Collectors.toSet()) 相比效率会低吗?

与将 HashSet 显式转换为 List O(n) 所需的时间相似,还是 Stream 与将元素添加回 List 或 Set 所需的时间不同?

数据集非常大。我想使用 List,因为它消耗的内存更少,但我不想为此牺牲速度。

代码示例:

Set<Object> originalSet;  // this is a set containing 800,000 Objects

// Scenario 1
List<Object> newList = originalSet.stream().filter(Object::isEnabled).collect(Collectors.toList())
   
// Scenario 2 
Set<Object> newSet = originalSet.stream().filter(Object::isEnabled).collect(Collectors.toSet())

【问题讨论】:

  • 你能展示一个代码示例而不是用文字描述代码吗? “一张图片胜过 1000 个字”
  • @StackOverthrow 从概念上讲,它与包含添加到新列表或集合的 if 语句的 for 循环没有什么不同。就是这样,但功能风格。
  • toListtoSet 都创建新的集合对象来存储结果。如果您从List 流式传输,其中一个不会突然变得更快。这能回答你的问题吗?
  • @LouisWasserman 您基本上是对的,但是“任何方面”都夸大了。流确实会根据源保留 一些 标志,这可能会对行为产生微妙的影响。列表中的流将具有 ORDERED 标志,而集合中的流应具有 DISTINCT 标志:ideone.com/QXTIpC

标签: java collections java-stream


【解决方案1】:

收集到列表比收集到集合更快。这是因为当收集到一个集合时,对于每个值,它需要找到它的哈希码,并根据这个哈希码知道该值在内存中的位置。

所以问题是我们应该总是收集到 List 而不是 Set 吗?不,这取决于情况。如果稍后在代码中需要检查某个元素是否存在于此列表或集合中,则搜索集合要快得多。在列表中搜索的复杂度是 o(n),而在集合上使用 .contains 只是 o(1)。 总而言之,如果您有使用 .contains 的代码,请使用 Set,但如果您稍后需要对其进行迭代,请使用 List。

【讨论】:

  • 这是“大 O”而不是“小 o”。但基本上,你是对的。主要关注点应该是“之后我需要什么?”如果它“只是一个集合”,那么收集到List 往往会更快,尤其是当您使用较新的toList() 操作时直接在Stream,而不是collect(…)
  • 我了解 List 和 Set 的优缺点,我想使用 List,但我只是担心我会花费额外的时间从 Set 转换为 List。所以基本上我在这篇文章中的问题是“这将花费与将 HashSet 显式转换为 List O(n) 相似的时间,还是 Stream 与将元素添加回 List 或添加元素所需的时间不同的状态不同?一套?”,我确实在问题的 cmets 中对此有所了解。
  • 你没有转换。您正在使用过滤器迭代元素并将接受的元素添加到新集合中。 Stream 可能对某些场景有内部优化,但这里不适用。请注意,即使您的起点是HashSet&lt;Object&gt; originalSet;,并且您正在做一个像HashSet&lt;Object&gt; copy = new HashSet&lt;&gt;(originalSet);(或originalSet.clone())这样的普通副本,在大多数环境都建立在其上的OpenJDK中也不会发生这种优化。换句话说,即使那样,new ArrayList&lt;&gt;(originalSet) 也会更快。
  • @Holger 这很有意义。谢谢!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2015-10-31
  • 1970-01-01
  • 2021-05-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多