是否值得将 distinct() 与 collect(toSet()) 一起使用
将流的元素收集到集合中时,在流上也指定是否有任何优点(或缺点)?例如:.distinct()
return items.stream().map(...).distinct().collect(toSet());
鉴于该集合已经删除了重复项,这似乎是多余的,但它是否提供了任何性能优势或劣势?答案是否取决于流是并行/顺序还是有序/无序?
将流的元素收集到集合中时,在流上也指定是否有任何优点(或缺点)?例如:.distinct()
return items.stream().map(...).distinct().collect(toSet());
鉴于该集合已经删除了重复项,这似乎是多余的,但它是否提供了任何性能优势或劣势?答案是否取决于流是并行/顺序还是有序/无序?
根据javadoc,是一个有状态的中间操作。distinct
如果你真的紧跟着 ,它并没有真正增加任何好处。也许如果实现比重复检查更高性能,你可能会得到一些好处,但如果你收集到一个集合,你最终会得到相同的结果。.distinct
.collect
.distinct
Set
另一方面,如果在操作之前发生,并且该特定映射是一项成本高昂的操作,则可能会获得一些收益,因为您总体上处理的数据较少。.distinct
.map
虽然你有相同的结果,但它们不会做同样的事情:使用,并且你失去了初始排序,这是不同可以保留的,如果需要的话:toSet()
HashSet
来自 javadoc:
在并行管道中保持 distinct() 的稳定性相对昂贵(要求操作充当完全屏障,并具有高缓冲开销),并且通常不需要稳定性。如果您的情况允许,使用无序流源(例如 generate(Supplier))或使用 BaseStream.unordered() 删除排序约束可能会显著提高并行管道中 distinct() 的执行效率。如果需要与遭遇顺序保持一致,并且您在并行管道中使用 distinct() 时遇到性能或内存利用率较差的情况,则使用 BaseStream.sequential() 切换到顺序执行可能会提高性能。
如果您需要稳定性,那么就是.使用 after 将毫无用处(如果 API 不需要)。distinct()
toSet()
但是,如果您实现了部分相等,这将非常有用: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)
但是,这需要一些先决条件(顺序等)。
注意:这可以使用适当的方法完成。TreeSet
compareTo