The problem is not really with ? extends ? extends ? extends ? extends , but with the identity parameter to reduce() . As Sotirios Delimanolis suggested, you can specify a limited type of N extends Number , but only if the identifier value is null .
public static <N extends Number> N reduceNum3(List<N> nums) { return nums.stream().reduce(null, (a, b) -> a); }
This is due to the fact that both wildcard and restricted methods cannot determine whether an identity parameter will be of the same type as the list items (if it is not null , which all types share).
To eliminate this problem, use the three-argument reduce() method, which allows you to consider the result as a different type (even if it is not really).
Here is a Number example:
public static Number reduceNum4(List<? extends Number> nums) { return nums.stream().reduce((Number)0, (a, b) -> a, (a, b) -> a); }
And here is the Set example:
public static <E> Set<E> reduceSet2(List<? extends Set<E>> sets) { return sets.stream().<Set<E>>reduce( ImmutableSet.<E>of(), Sets::union, Sets::union); }
Itβs a little annoying that you have to duplicate the reduction function, since accumulator and combiner different types. You could probably define it once in a variable and pass it to both through an unsafe cast, but I'm not quite sure if this is an improvement. Using method references is probably the right way.
dimo414
source share