You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

200元素列表取唯一值:两种Stream操作的延迟与内存效率对比

Stream distinct() + toList() vs toSet():效率对比分析

嘿,这个问题问得挺实在的——处理重复元素时,选对方法确实能在性能上带来小惊喜。结合你说的「200个元素、仅20个唯一」的场景,咱们从延迟(执行时间)和内存消耗两方面拆解这两种写法的差异:

内存消耗对比

  • list.stream().collect(Collectors.toSet()):
    默认底层用的是HashSet(除非你指定其他Set实现)。HashSet的结构是数组+链表/红黑树,它会在遍历列表的同时直接去重存储。对于你的场景,最终只需要存20个唯一元素,HashSet初始容量默认是16,超过负载因子(0.75)后会扩容到32,内存占用就是HashSet自身结构加上20个元素的引用空间,全程只维护这一个集合。

  • list.stream().distinct().collect(Collectors.toList()):
    distinct()操作内部其实是靠LinkedHashSet来记录已出现的元素(目的是保证元素和原列表中第一次出现的顺序一致),之后还要把LinkedHashSet里的元素复制到List(比如默认的ArrayList)中。这意味着内存里会同时存在两个集合:一个存20个元素的LinkedHashSet,一个存同样20个元素的ArrayList。虽然元素是引用,但LinkedHashSet的链表节点会额外占用一点内存,整体内存开销比toSet()略高。

延迟(执行时间)对比

  • toSet()更直接高效:
    它是一步到位的操作:遍历列表时直接将元素加入HashSet去重,最后返回Set。全程只遍历一次元素,没有额外的复制步骤。对于你的场景,200个元素遍历一次,加上20个元素的哈希检查,速度很快。

  • distinct().toList()多了一次复制步骤:
    首先要遍历200个元素,用LinkedHashSet去重;然后还要遍历这个只有20个元素的LinkedHashSet,把元素复制到List里。相当于两次遍历(虽然第二次遍历的元素很少)。另外,LinkedHashSet因为要维护顺序,插入时比HashSet多了一点链表维护的开销,不过这个开销在元素少的时候几乎可以忽略。

结合你的场景总结

  • 如果不需要保留原列表的元素顺序,toSet()在内存和速度上都更优,而且代码更简洁。
  • 如果必须保留元素第一次出现的顺序,那distinct().toList()是标准选择,虽然内存和速度略逊,但在20个唯一元素的场景下,差异非常小,几乎感知不到。

额外提醒:两种方法的性能都依赖于你的对象的hashCode()和equals()实现——如果这两个方法写得低效,那不管选哪种写法,性能都会打折扣。

内容的提问来源于stack exchange,提问作者Laxmikant

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.19 10:18:10