这answer提供对 IntStream 进行分区的实现:
IntStream intStream = IntStream.iterate(0, i -> i + 1).limit(1000000);
Predicate<Integer> p = x -> r.nextBoolean();
Map<Boolean, List<Integer>> groups = intStream.collect(() -> {
Map<Boolean, List<Integer>> map = new HashMap<>();
map.put(false, new ArrayList<>());
map.put(true, new ArrayList<>());
return map;
}, (map, x) -> {
boolean partition = p.test(x);
List<Integer> list = map.get(partition);
list.add(x);
}, (map1, map2) -> {
map1.get(false).addAll(map2.get(false));
map1.get(true).addAll(map2.get(true));
});
System.out.println(groups.get(false).size());
System.out.println(groups.get(true).size());
但是它的编辑提到这个实现不是线程安全的。然而,据我所知,收集器创建了一个单独的 HashMap<List<Integer>>
对于并行流中的每个线程。所以每个映射都被限制在一个线程中。分区功能也仅限于单个线程。合并函数合并来自多个线程的结果,但据我所知,流框架确保合并以线程安全的方式完成。所以我的问题是:这个解决方案真的不是线程安全的吗?
顺便说一句:无论如何,答案提供了一个更优雅的解决方案(Stream<Integer> stream = intStream.boxed();
等),但我仍然想知道。
PS:我想将这个问题添加为对原始帖子的评论,但我什至没有添加评论的声誉...:|
最佳答案
根据 Oracles 文档
Like reduce(int, IntBinaryOperator), collect operations can be parallelized without requiring additional synchronization.
看来您的直觉是正确的,这是线程安全的。
关于java - 这个 IntStream 分区实现真的不是线程安全的吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61251704/