在Arrays.reduce(...)中调用对象方法

new*_*bie 15 java oop object java-8

我有以下3个文件,

A.java:

class A {

    private float b;    

    public A(float b) {
        this.b = b;
    }

    public float getB() {
        return b;
    }

}
Run Code Online (Sandbox Code Playgroud)

C.java:

import java.util.Arrays;

class C {

    private A[] d;
    private int i = 0;

    public C() {
        d = new A[2];
    }

    public float totalB() {
        return Arrays.stream(d).reduce((e, f) -> e.getB() + f.getB()).get();
    }

    public void addB(A b) {
        d[i++] = b;
    }

}
Run Code Online (Sandbox Code Playgroud)

D.java:

class D {

    public static void main(String[] args) {
        C c = new C();
        c.addB(new A(3));
        c.addB(new A(5));
        System.out.println(c.totalB())
    }

}
Run Code Online (Sandbox Code Playgroud)

我期待D.java中的最后一行输出8,但是我得到了这个错误:

error: incompatible types: bad return type in lambda expression return Arrays.stream(d).reduce((e, f) -> e.getB() + f.getB()).get(); ^ float cannot be converted to A 为什么会这样?我没有看到我将浮子转换为对象A.

Ous*_* D. 13

我更喜欢使用"sum"方法,因为它比一般reduce模式更具可读性.即

return (float)Arrays.stream(d)
                    .mapToDouble(A::getB)
                    .sum();
Run Code Online (Sandbox Code Playgroud)

与您的方法相反,这是更惯用,可读和有效的方法Arrays.stream(d).reduce(...).

  • @AnkurChrungoo请记住,流不是关于存储,而只是计算.一旦JIT/HotSpot优化器完成其工作,所有中间值仍然存在于CPU寄存器中,并且CPU寄存器始终具有相同的宽度.唯一的缺点是没有办法从流中创建一个`float []`数组.但是在这里,我们只得到一个最终值,我们无论如何都可以.其中一位API开发人员曾在SO评论中曾表示他们甚至考虑省略`IntStream`而赞成使用'LongStream`,但觉得"开发人员还没准备好(还)"...... (4认同)

Era*_*ran 11

单个参数reduce()变体期望reduce操作的最终结果与Stream元素的类型相同.

您需要一个不同的变体:

<U> U reduce(U identity,
             BiFunction<U, ? super T, U> accumulator,
             BinaryOperator<U> combiner);
Run Code Online (Sandbox Code Playgroud)

您可以使用如下:

public float totalB() {
    return Arrays.stream(d).reduce(0.0f,(r, f) -> r + f.getB(), Float::sum);
}
Run Code Online (Sandbox Code Playgroud)

  • 或Arrays.stream(d).reduce(0,(r,f) - > r +(int)f.getB(),Integer :: sum); (3认同)