0

Given this attempt to implement a sum :

int[] nums = { 1,3,4,5,7};
var sum = Arrays.asList(nums).stream().reduce(0,(a,b)->a+b);          

Problems like the following are typically due to insufficient type information provided to the compiler for type inference. But here we have a non-ambiguous int[] array as the source. Why is this error then happening?

Line 3: error: no suitable method found for reduce(int,(a,b)->a + b)
        var sum = Arrays.asList(nums).stream().reduce(0,(a,b)->a+b);
                                              ^
    method Stream.reduce(int[],BinaryOperator<int[]>) is not applicable
      (argument mismatch; int cannot be converted to int[])
    method Stream.<U>reduce(U,BiFunction<U,? super int[],U>,BinaryOperator<U>) is not applicable
      (cannot infer type-variable(s) U
        (actual and formal argument lists differ in length))
  where U,T are type-variables:
    U extends Object declared in method <U>reduce(U,BiFunction<U,? super T,U>,BinaryOperator<U>)
    T extends Object declared in interface Stream

4

2 Answers 2

3

var sum = Arrays.asList(nums) returns a List<int[]> and consequently the reduce method adds int[] to int[]. This is not allowed and leads to a compilation error.

This is a possible solution:

int[] nums = { 1,3,4,5,7};
var sum= Arrays.stream(nums).reduce(0,(a,b)->a + b);

or

var result = Arrays.stream(nums).sum();
Sign up to request clarification or add additional context in comments.

1 Comment

ah nice catch. That's a pretty quick first accepted answer - congrats!
0

Since nums is an array of primitives (int[]), not an array of objects (e.g. Integer[]), its elements are not treated as varargs arguments to Arrays.asList(T... a). Rather, the whole int[] is treated as a single argument. This results in a list of type List<int[]> with a single element: the int[] value nums.

Since this is a Stream<int[]>, the compilation fails since the reduce lambda (a, b)->a+b is attempting to add two int[] values together using +, which is not a valid operator for two arrays.

Changing nums to an array of objects causes Arrays.asList to work as originally intended:

Integer[] nums = {1,3,4,5,7};
var sum = Arrays.asList(nums).stream().reduce(0,(a, b)->a+b);

That said, this results in needless boxing and unboxing between Integer and int. It would be better to use an IntStream of the array using the Arrays.stream method:

int[] nums = {1,3,4,5,7};
var sum = Arrays.stream(nums).reduce(0,(a, b)->a+b);

The Arrays.stream(nums) call creates an IntStream of the array's elements. This is then reduced to the sum using its reduce(int identity, IntBinaryOperator op) method.

Summing values of an IntStream can be simplified further to use sum instead of reduce:

int[] nums = {1,3,4,5,7};
var sum = Arrays.stream(nums).sum();

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.