【问题标题】:Java parallel stream with nested HashMap具有嵌套 HashMap 的 Java 并行流
【发布时间】:2018-10-25 14:33:05
【问题描述】:

鉴于嵌套的 HashMap HashMap<Integer,HashMap<Integer,BigDecimal>> 是否可以使用并行流将内部 HashMap 值设置为零 可接受的副作用和尊重不干涉规则?

例如,给定HashMap:

HashMap<Integer,HashMap<Integer,BigDecimal>> myMap = null;

是最终的forEach:

myMap.entrySet().parallelStream().forEach(e -> {
            e.getValue().entrySet().parallelStream().forEach(e1 -> {
                e1.setValue(new BigDecimal(0));
                });
        });

可接受的副作用和尊重不干扰规则?

【问题讨论】:

  • 我已经投票结束这个问题,因为不清楚你在问什么。请参阅:stackoverflow.com/help/how-to-ask 并相应地编辑问题。
  • 查看这个问题的答案:stackoverflow.com/questions/32837415/…
  • 基本上,我询问代码是否尊重 Java Stream 文档中报告的模式,特别是在涉及非干扰和副作用规则时。
  • 这可能是由于HashMap 的条目的setValue 方法已实现的方式,至少当您可以保证没有哈希映射实例在外部出现多次时地图的价值。但是,myMap.values().forEach(m -&gt; m.replaceAll((k,v) -&gt; BigDecimal.ZERO)); 怎么样?与您的并行操作相比,它的运行速度快了多少?

标签: java java-stream


【解决方案1】:

...是否可以使用并行流将内部 HashMap 值设置为零...

它似乎有效,但是HashMap 不是线程安全的实现,所以我不鼓励你使用这种方式。

...具有可接受的副作用并尊重不干扰规则?

你对Stream::for的使用有副作用,因为它改变了流的来源。我建议您使用Stream::map,然后使用parrallelStream 将结构收集回Map

Map<Integer, Map<Integer,BigDecimal>> myMap2 = myMap.entrySet().parallelStream()
    .map(e -> new AbstractMap.SimpleEntry<>(
        e.getKey(), 
        e.getValue().entrySet().stream()
                               .collect(Collectors.toMap(Entry::getKey, i -> BigDecimal.ZERO))))
    .collect(Collectors.toMap(Entry::getKey, Entry::getValue));

【讨论】:

  • 在使用toMap 收集之前,无需mapSimpleEntry。您作为 SimpleEntry 构造函数的参数编写的内容可以直接写入指定给 toMap 收集器 (myMap.entrySet().parallelStream() .collect(Collectors.toMap(Entry::getKey, e -&gt; e.getValue().entrySet().stream() .collect(Collectors.toMap(Entry::getKey, i -&gt; BigDecimal.ZERO)) ));) 的函数中。
  • 所以我可以得出结论,我的原始代码有效,但更改可变数据不能被视为纯粹的功能。无论如何,它似乎与流 Javadoc 兼容,因为那里没有明确要求纯粹的功能行为。 Holger 的代码也是纯函数式的。
猜你喜欢
  • 1970-01-01
  • 2016-08-27
  • 1970-01-01
  • 2019-01-16
  • 2014-03-25
  • 2014-10-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多