gpt4 book ai didi

java - Collectors.toSet 实现细节

转载 作者:塔克拉玛干 更新时间:2023-11-03 04:58:04 24 4
gpt4 key购买 nike

我正在查看 jdk-8 下的 Collectors.toSet 实现并且几乎看到了显而易见的事情:

 public static <T> Collector<T, ?, Set<T>> toSet() {
return new CollectorImpl<>(
(Supplier<Set<T>>) HashSet::new,
Set::add,
(left, right) -> { left.addAll(right); return left; }, // combiner
CH_UNORDERED_ID);

看一下组合器;这之前已经讨论过here ,但想法是组合器从第二个参数折叠到第一个参数。这显然发生在这里。

但后来我查看了 jdk-9 实现并看到了这个:

 public static <T> Collector<T, ?, Set<T>> toSet() {
return new CollectorImpl<>(
(Supplier<Set<T>>) HashSet::new,
Set::add,
(left, right) -> {
if (left.size() < right.size()) {
right.addAll(left); return right;
} else {
left.addAll(right); return left;
}
},
CH_UNORDERED_ID);

现在为什么会发生这种情况有点明显 - 将较少的元素添加到更大的 Set 花费的时间更少,然后相反。但这真的比普通的 addAll 便宜吗,还要考虑分支的额外开销吗?

这也违反了我关于总是向左折叠的法则...

有人可以在这里阐明一些问题吗?

最佳答案

Collector 的组合器函数将接收 leftright,如果遇到然而,为了维护,这取决于 Collector,它如何实际组合这两个参数。

documentation状态:

A function that accepts two partial results and merges them. The combiner function may fold state from one argument into the other and return that, or may return a new result container.

为了收集到 List,如果我们只是将 left.addAll(right) 换成 right.addAll(left),那将是灾难性的>,但对于无序的 Set,这无关紧要。 toSet() 收集器甚至报告 UNORDEREDStream(或任何客户端代码)暗示哪个参数被提供为 leftright 的特征都没有关系,所以并行流可以组合任意部分结果,无论先完成的是什么,换句话说,它可能表现得像无序流,即使源有遇到顺序(Java 8 的实现不利用这个机会)。

关于这是否值得......我们正在比较一个额外的分支与我们可以节省的可能数千个 add 操作,每个承载多个 内部条件分支...

关于java - Collectors.toSet 实现细节,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43767685/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com