[英]Is it worth using distinct() with collect(toSet())
将流的元素收集到集合中时,是否还有优势(或缺点)在流上指定.distinct()
? 例如:
return items.stream().map(...).distinct().collect(toSet());
鉴于该集合已经删除了重复项,这似乎是多余的,但它是否提供任何性能优势或劣势? 答案取决于流是并行/顺序还是有序/无序?
根据javadoc , distinct
是一个有状态的中间操作。
如果你确实有.distinct
紧跟着.collect
,那么它并没有真正增加任何好处。 也许如果.distinct
实现比Set
重复检查更.distinct
,你可能会获得一些好处,但是如果你收集到一个集合,你最终会得到相同的结果。
另一方面,如果.distinct
发生在.map
操作之前,并且该特定映射是一项昂贵的操作,那么您可能会获得一些收益,因为您整体处理的数据较少。
虽然你有相同的结果,但它们不会做同样的事情: toSet()
使用HashSet
,你失去了初始排序,如果需要,它可以保留不同的东西:
来自javadoc :
保持并行管道中不同()的稳定性相对昂贵(要求操作充当完全屏障,具有大量缓冲开销),并且通常不需要稳定性。 如果您的情境的语义允许,使用无序流源(例如generate(Supplier))或使用BaseStream.unordered()删除排序约束可以显着提高并行管道中distinct()的执行效率。 如果需要与遇到顺序的一致性,并且您在并行管道中使用distinct()遇到性能不佳或内存利用率,则切换到使用BaseStream.sequential()的顺序执行可能会提高性能。
如果你需要稳定性,那么它是distinct()
。 之后使用toSet()
将是无用的(如果API不需要)。
但是,如果你有一个equals
实现部分相等的equals
:
class F {
int a;
int b;
@Override int hashCode() {return Objects.hashCode(a);}
@Override boolean equals(Object other) {
if (other == this) return true;
if (!(other instanceof F)) return false;
return a == ((F)other).a;
}
}
如果你有a = F(10, 1)
和b = F(10, 2)
它们是等于。 但并非所有领域都是平等的。
如果在列表中你有(b, a)
toSet()
您将无法始终拥有此订单。 你可能有(b,a)等 (b, a)
。 然而,这假设了一些先决条件(顺序等)。
注意:这可以使用TreeSet
和适当的compareTo
方法完成。
distinct会调用equals / hashcode来分隔项目,之后toSet会做同样的事情(即使在不需要之后,但是toSet也不能真正知道),所以基本上你只是重复调用。 它应该表现稍差IMO。 测量也很容易。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.