【问题标题】:Reduce from array of integers to double in java 8在 java 8 中从整数数组减少到双精度
【发布时间】:2015-03-10 18:06:18
【问题描述】:

这是我的代码:

// assuming HashMap<String, Integer> hashmap
double sum = hashmap.values().stream()
    .reduce(.0, (i, v) -> i + Math.pow(v,2) + 0.5 );

在这种情况下,reduce 应该采用 (Integer i) 和 (double v) 并将它们相加,然后将此 reduce 作为双精度数返回。

相反,我得到了这个错误:

- The method reduce(Integer, BinaryOperator<Integer>) in the type Stream<Integer> is not applicable for the arguments (double, (<no type> i, <no type> v) -> {})

- Type mismatch: cannot convert from double to Integer

减少,

但是,这修复了:

// assuming HashMap<String, Integer> hashmap
double sum = hashmap.values().stream()
    .map((t)->(double)t)
    .reduce(.0, (i, v) -> i + Math.pow(v,2) + 0.5 );

有没有更优雅的方法?

【问题讨论】:

  • 就您期望发生的事情而言,我不清楚您实际上要实施什么操作。你能用普通的 for-each 编写一个实现来更清楚吗?

标签: java java-8 java-stream


【解决方案1】:

您只是想对v * v + 0.5 的值求和吗?

如果是这样,最清晰的解决方案是

double sum = 0;
for (int v : hashmap.values())
    sum += v * v + 0.5;

如果您必须使用流,答案是

double sum = hashmap.values().stream().mapToDouble((v) -> v * v + 0.5).sum();

但是尝试使用reduce() 执行此操作是没有意义的,因为0.0 不是累加器的标识,并且累加器不是关联的。

【讨论】:

  • 猜对了。如果这是预期的操作,hashmap.values().stream().mapToDouble(v-&gt;v*v).sum()+0.5*hashmap.size(); 会更有效率……
【解决方案2】:

BinaryOperator 必须接受两个相同类型的参数。但是,您肯定想使用

double sum = hashmap.values().stream().mapToDouble(Integer::doubleValue)
  .reduce(.0, (i, v) -> i + Math.pow(v,2) + 0.5 );

为了避免不必要的装箱转换,因为Stream.mapToDouble(…)Stream 转换为DoubleStream。相反,在 Stream 上调用 .map((t)-&gt;(double)t) 将在 Integer 实例之外创建 Double 实例。


但请注意,您对reduce 的使用违反了它的合同。第一个参数(您在此处使用0.)必须是归约函数的标识值。 “标识值”意味着对于任何值vapply(identity, v) 必须导致v,而这里不是这种情况。不符合身份合约can lead to surprising behavior

【讨论】:

    猜你喜欢
    • 2016-06-14
    • 2019-07-13
    • 2014-11-10
    • 1970-01-01
    • 2018-04-01
    • 2011-09-18
    • 2017-10-17
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多