使用collect时的并发数据结构和并行流

Adi*_*hya 2 lambda java-8 java-stream

在通过以下答案讨论在流中使用并发数据结构以及使用并发映射和转换为映射之间的不同之后,有人可以解释如果我使用collectie 的其他语法将会发生什么

    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);
Run Code Online (Sandbox Code Playgroud)

根据文档,将根据生成的线程数调用供应商.如果我使用ConcurrentHashMap而不是HashMap

当并行执行时,可以实例化,填充和合并多个中间结果,以便保持可变数据结构的隔离.因此,即使与非线程安全数据结构(例如ArrayList)并行执行,也不需要额外的同步来进行并行缩减.

Hol*_*ger 5

当您使用ConcurrentHashMap而不是HashMap使用three-arg collect方法时,不会有行为改变.要更改行为,您需要一个Collector报告CONCURRENT特征的方法,并且无法使用ad-hoc收集器指定特征.

此外,操作必须是无序的以启用并行收集操作,其中所有线程累积到单个容器中.由于流属性,操作可能是无序的,或者是内在的,例如当流过诸如a的无序源时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));
Run Code Online (Sandbox Code Playgroud)

或者由于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));
Run Code Online (Sandbox Code Playgroud)

后者是使用内置收集器时得到的:

Map<Integer, Boolean> resultMap = integers.limit(1000)
    .collect(Collectors.toConcurrentMap(Function.identity(), i -> Boolean.FALSE));
Run Code Online (Sandbox Code Playgroud)

toConcurrentMap将永远是CONCURRENT并且UNORDERED并且需要ConcurrentMap在您使用地图供应商时,即使您提供创建实施实例的供应商,toMap也永远不会.CONCURRENTConcurrentMap

  • 相当精细!赞赏. (2认同)