gpt4 book ai didi

Java流-收集组合器

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

为什么会出现下面的代码:

StringBuilder sb22 = IntStream
.range(1, 101)
.filter(x -> x > 50)
.boxed()
.parallel()
.collect(// object that is used in accumulator to do accumulating on
StringBuilder::new,
// use object from above and call append on it with each stream element as argument
(sb, a) -> sb.append(":" + a),
// (executes only when using parallel!)
(sb1, sb2) -> {
System.out.println(Thread.currentThread().getId() + " " + "sb1=" + sb1 + " AND " + "sb2=" + sb2);
sb1.append("-"+sb2);
});

产生这个结果:

------------------:51:52:53-:54:55:56-:57:58:59-:60:61:62-:63:64:65-:66:67:68-:69:70:71-:72:73-:74:75-:76:77:78-:79:80:81-:82:83:84-:85:86:87-:88:89:90-:91:92:93-:94:95:96-:97:98-:99:100

第一部分 (----------------) 不应该从输出中排除吗?

此外,我了解到 collect 中的组合器可能会被乱序调用,因此可以改为 :76:77:78-:79:80:81 例如:63:64:65-:79:80:81?

更新(@Holger 回复后)

这是使用他为此案例链接的代码生成的树:

                                                                                                                                                    [51..100]                                                                                                                                                     
_________________________________________________________________________________/\______________________________________________________________________
| |
(empty) [51..100]
___________________________________/\__________________________________ ________________________________________/\______________________________________
| | | |
(empty) (empty) [51..75] [76..100]
___________________/\______________ ___________________/\______________ ______________________/\________________ ______________________/\________________
| | | | | | | |
(empty) (empty) (empty) (empty) [51..62] [63..75] [76..87] [88..100]
_______/\______ ___________/\______ _______/\______ ___________/\______ ________/\_______ _____________/\_______ ________/\_______ _____________/\_______
| | | | | | | | | | | | | | | |
(empty) (empty) (empty) (empty) (empty) (empty) (empty) (empty) [51..56] [57..62] [63..68] [69..75] [76..81] [82..87] [88..93] [94..100]
___/\__ ___/\__ ___/\__ _______/\__ ___/\__ ___/\__ ___/\__ _______/\__ ___/\___ ___/\___ ___/\___ ________/\__ ___/\___ ___/\___ ___/\___ ________/\___
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
(empty) (empty) (empty) (empty) (empty) (empty) (empty) (empty) (empty) (empty) (empty) (empty) (empty) (empty) (empty) (empty) [51..53] [54..56] [57..59] [60..62] [63..65] [66..68] [69..71] [72..75] [76..78] [79..81] [82..84] [85..87] [88..90] [91..93] [94..96] [97..100]
___/\__ ___/\__ ___/\___ ____/\__
| | | | | | | |
(empty) (empty) (empty) (empty) [72..73] [74..75] [97..98] [99..100]

最佳答案

工作负载拆分发生在处理任何内容之前,因此,Stream 实现会将范围 [1, 101] 拆分为要处理的子范围。此时,它不知道过滤器将完全删除前半部分,如果不评估谓词就无法知道,而且这应该已经并行发生,因此,在工作负载拆分之后。

因此,每个子范围都以相同的方式处理,包括将结果收集到一个容器中,然后将这些容器组合起来,即使它们恰好是空的。规范并没有说当没有元素到达收集器时将跳过组合步骤,因此,你不应该期望这样。虽然从理论上讲,可以跟踪是否有任何元素到达收集器,但这种跟踪仅适用于特定情况,甚至不清楚是否将容器与空容器组合(例如添加空 List 或附加一个空的 StringBuilder) 比此跟踪更昂贵。

当然,没有什么能阻止你优化你的组合器,如果它保留了语义,例如代替 (sb1, sb2) -> sb1.append(sb2),你可以使用 (sb1, sb2) -> sb1.length()==0? sb2: sb1.append(sb2)

可以看看this Q&A, “Visualization of Java Stream parallelization”了解更多详情。

关于Java流-收集组合器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49111653/

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