Reputation: 354
When using stream, very similar two pieces of code behave differently.
I cannot understand what the compiler's error is trying to convey.
import java.util.Arrays;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
import static java.util.stream.Collectors.toList;
public class Main {
public static void main(String[] args) {
// Pythangorian stream
List<List<Integer>> ret = IntStream.range(1, 10).boxed()
.flatMap(a -> IntStream.range(a, 10)
// This works fine...
// .mapToObj(b -> Arrays.asList(a, b, a*a + b*b))
.mapToObj(b -> Arrays.asList(a, b, Math.sqrt(a*a + b*b)))
// .filter(t -> Math.sqrt(t.get(2)) % 1 == 0))
.filter(t -> t.get(2) % 1 == 0))
.collect(toList());
System.out.println(ret);
}
}
If Math.sqrt
is used in mapToObj
, it gets compiler error. If not, it works fine. The error message is like so:
Error:(21, 62) java: bad operand types for binary operator '%'
first type: java.lang.Number&java.lang.Comparable<? extends java.lang.Number&java.lang.Comparable<?>>
second type: int
Error:(22, 25) java: incompatible types: inference variable T has incompatible bounds
equality constraints: java.util.List<java.lang.Integer>
lower bounds: java.util.List<java.lang.Number&java.lang.Comparable<? extends java.lang.Number&java.lang.Comparable<?>>>
Can someone please tell me what this error message is saying? I am aware of my little knowledge in Java is the main concern. Can you please guide me where to look to understand this?
Upvotes: 1
Views: 79
Reputation: 4331
The reason is you are trying to collect
to List<Integer>
but you should use List<? extends Number>
instead. Moreover your filter
method can be removed because this condition is always true, i.e. any integer can be divided by one without remainder.
Working code can look like this:
List<List<? extends Number>> ret = IntStream.range(1, 10)
.boxed()
.flatMap(a -> IntStream.range(a, 10)
.mapToObj(b -> Arrays.asList(a, b, Math.sqrt(a * a + b * b))))
.collect(toList());
The reason is Math.sqrt()
returns double
and a
and b
are integers so you cannot collect
all of these three to List<Integer>
. The second approach is to collect
to List<Double>
and use explicit cast from integer to double:
List<List<Double>> ret = IntStream.range(1, 10)
.boxed()
.flatMap(a -> IntStream.range(a, 10)
.mapToObj(b -> Arrays.asList((double) a, (double) b, Math.sqrt(a * a + b * b))))
.collect(toList());
Upvotes: 4