Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Calling object methods within Arrays.reduce(...)

I have the following 3 files,

A.java:

class A {

    private float b;    

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

    public float getB() {
        return b;
    }

}

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;
    }

}

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())
    }

}

I was expecting the last line in D.java to output 8, however I get this error:

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 Why does this happen? I don't see where I'm converting the floats to the object A.

like image 841
newbie Avatar asked Nov 15 '18 14:11

newbie


People also ask

Can you use reduce on array of objects?

If you use array reduce on an array without any elements and don't provide initialValue, it will throw a TypeError. If the array is empty and initialValue is provided, or the array has only one element and initialValue, the reduce method will return the same value without calling the callbackfn.

How do you call reduce on an array of objects to sum their properties?

const sum = values. reduce((accumulator, currentValue) => { return accumulator + currentValue; } , 0); As you can see, the reduce method executes the call back function multiple times. For each time, it takes the current value of the item in the array and sum with the accumulator.

Can you use reduce on objects?

But did you know you can reduce them to objects as well? First, a quick overview of how reduce works. The reduce method receives two arguments: a function and an initial value. The function will run run for every value in the array, and receives two arguments as well: the accumulator, or acc , and the current value .

What is the reduce () array method?

The reduce() method executes a user-supplied "reducer" callback function on each element of the array, in order, passing in the return value from the calculation on the preceding element. The final result of running the reducer across all elements of the array is a single value.


2 Answers

I prefer utilizing the "sum" method as it's more readable than the general reduce pattern. i.e.

return (float)Arrays.stream(d)
                    .mapToDouble(A::getB)
                    .sum();

This is the more idiomatic, readable and efficient approach as opposed to your approach of Arrays.stream(d).reduce(...)...

like image 152
Ousmane D. Avatar answered Oct 17 '22 11:10

Ousmane D.


The single argument reduce() variant expects the final result of the reduce operation to be of the same type as the Stream elements.

You need a different variant:

<U> U reduce(U identity,
             BiFunction<U, ? super T, U> accumulator,
             BinaryOperator<U> combiner);

which you can use as follows:

public float totalB() {
    return Arrays.stream(d).reduce(0.0f,(r, f) -> r + f.getB(), Float::sum);
}
like image 39
Eran Avatar answered Oct 17 '22 09:10

Eran