在完成以下有关using concurrent data structures in streams和different between using concurrent map and converting to a map的答案后,有人可以解释如果我使用collect
的其他语法,即会发生什么。
Stream<Integer> integers = Stream.iterate(1, n -> n + 1).parallel();
Map<Integer, Boolean> resultMap = integers
.limit(1000)
.collect(HashMap::new,
(map, value) -> map.put(value, false),
HashMap::putAll);
根据文档,将根据生成的线程数调用供应商。如果我使用ConcurrentHashMap
而不是HashMap
怎么办?
当并行执行时,可能会有多个中间结果 实例化,填充和合并以便保持隔离 可变数据结构。因此,即使并行执行 使用非线程安全的数据结构(如ArrayList),没有 并行缩减需要额外的同步。
答案 0 :(得分:5)
使用{-1}}代替ConcurrentHashMap
时,使用三个{arg HashMap
方法时,不会发生任何行为更改。要更改行为,您需要collect
来报告CONCURRENT
特征,并且无法使用ad-hoc收集器指定特征。
此外,操作必须是无序的,以启用并行收集操作,其中所有线程累积到单个容器中。由于流属性,该操作可能是无序的,或者是本质上,例如,在Collector
之类的无序来源上流式传输时,或通过HashSet
显式流式传输,例如
unordered()
或由于收集者的Map<Integer, Boolean> resultMap = integers.limit(1000)
.unordered()
.collect(Collector.of(
() -> new ConcurrentHashMap<>(),
(map, value) -> map.put(value, false),
(m1,m2) -> { m1.putAll(m2); return m1; },
Collector.Characteristics.CONCURRENT));
特征:
UNORDERED
后者是你在使用内置收集器时得到的:
Map<Integer, Boolean> resultMap = integers.limit(1000)
.collect(Collector.of(
() -> new ConcurrentHashMap<>(),
(map, value) -> map.put(value, false),
(m1,m2) -> { m1.putAll(m2); return m1; },
Collector.Characteristics.CONCURRENT, Collector.Characteristics.UNORDERED));
Map<Integer, Boolean> resultMap = integers.limit(1000)
.collect(Collectors.toConcurrentMap(Function.identity(), i -> Boolean.FALSE));
始终为toConcurrentMap
和CONCURRENT
,当您使用地图供应商时需要UNORDERED
,而ConcurrentMap
永远不会toMap
即使您提供了创建CONCURRENT
实施实例的供应商。
答案 1 :(得分:2)
准确地说,即使你使用ConcurrentHashMap
个线程,也不会共享数据,并且会有尽可能多的ConcurrentHashMap,因为supplier
将被称为no。时间。 combiner
即最后一个BiConsumer参数将执行合并操作但是没有顺序,即无论哪个线程完成抛出数据,然后合并。
当你明确地说Collectors.toConcurrentMap
时,收集器行为是一个单个容器(即ConcurrentHashMap)所有线程将推送数据&amp;不需要合作。