【问题标题】:Java 7 => Java 8 : for to foreach on a Map with calculationJava 7 => Java 8:用于在地图上进行计算
【发布时间】:2016-12-02 16:30:11
【问题描述】:

我从 Java 8 开始,我有一个迁移项目。我已经阅读了很多使用 foreach 或流的文档和教程,但我还有一个小问题。我没有找到答案,只是简单的教程示例。

我正在尝试改变这个循环:

for ( Map.Entry<Neuron, Double> entry: this.entries.entrySet() ) {
     value += entry.getKey().getExitValue() * entry.getValue();
}

此解决方案不匹配,我知道原因(匿名 class=> 最终/本地变量)

this.entries.forEach( (neuron, weight) -> {
      value += neuron.getExitValue() * weight;
});

但只有一个 foreach 我不知道这个简单的操作是怎么做的。

我认为这很容易,但是...

我尝试过使用流,但我遇到了类似的问题。

Double sum = entries.entrySet()
    .stream()
    .forEach( entry-> { ? } );

提前谢谢你。

【问题讨论】:

  • 不要用forEach替换循环。这不是一个改进。如果您要进行函数式编程,最好忘记forEach 的存在。由于您是从条目计算的 summing 值,因此您应该考虑这个方向,即value = entries.entrySet().stream() .mapToDouble(e -&gt; e.getKey().getExitValue() * e.getValue()) .sum()
  • @Holger 这应该是一个答案。
  • 您好,正确答案。我在想这个周末,迁移这个循环没有用(因为在这种情况下不是函数式编程)。您与 mapToDouble 的解决方案也正确匹配。祝你今天过得愉快。谢谢。

标签: dictionary lambda java-8 java-stream


【解决方案1】:

正如@Holger 在上面的 cmets 中所说 - 在这种情况下,最好使用 mapToDoble。但是仍然有一种方法可以使用forEach 循环。 请注意,这是一个丑陋、肮脏的把戏,仅用于演示目的,不应在生产代码中使用。我们知道只有 final 或有效的 final 变量可以与 lambda 表达式一起使用,这就是为什么value += 是非法表达式。 Java-8 向java.util.concurrent.atomic 添加了一些新类,其中之一是DoubleAdder。您可以将它与 lambda 一起使用:

DoubleAdder adder = new DoubleAdder();
stream.forEach(e -> adder.add(e.getKey().getExitValue() * e.getValue()));
System.out.println(adder.sum());

我没有看到任何应该使用它来代替 mapToDouble 的情况

【讨论】:

  • 有趣的方法,当然丑陋但棘手。 不保证线程内或跨线程的累积顺序。因此,如果需要数值稳定性,则此类可能不适用,尤其是在组合具有显着不同数量级的值时不幸的是,我们需要它用于此应用程序(神经网络)。感谢您的回答,对我来说非常有趣。
【解决方案2】:

我引入了一个列表来停止值,然后用列表进行计算。

final List<BigDecimal> valuesList = new ArrayList<>();
otherList.stream().forEach(val-> valuesList.add(map.get(val)));
final BigDecimal lastValue = valuesList.stream().filter(Objects::nonNull).reduce(BigDecimal.ZERO,BigDecimal::add);

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-06-30
    • 1970-01-01
    • 1970-01-01
    • 2016-01-06
    • 1970-01-01
    • 1970-01-01
    • 2019-02-24
    • 1970-01-01
    相关资源
    最近更新 更多