【发布时间】:2015-06-25 04:44:08
【问题描述】:
我正在试验Stream.reduce(),但遇到了类型系统的障碍。这是一个玩具示例:
public static Number reduceNum1(List<Number> nums) {
return nums.stream().reduce(0, (a, b) -> a);
}
这适用于任何List<Number>,但是如果我希望能够减少? extends Number 的列表怎么办?这不编译:
public static Number reduceNum2(List<? extends Number> nums) {
return nums.stream().reduce((Number)0, (a, b) -> a);
}
出现错误:
ReduceTest.java:72: error: no suitable method found for reduce(Number,(a,b)->a)
return nums.stream().reduce((Number)0, (a, b) -> a);
^
method Stream.reduce(CAP#1,BinaryOperator<CAP#1>) is not applicable
(argument mismatch; Number cannot be converted to CAP#1)
method Stream.<U>reduce(U,BiFunction<U,? super CAP#1,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
where CAP#1 is a fresh type-variable:
CAP#1 extends Number from capture of ? extends Number
Note: Some messages have been simplified; recompile with -Xdiags:verbose to get full output
从概念上讲,我明白为什么会发生这种情况。 Stream.reduce() 必须返回与源元素相同类型的东西,并且? extends Number 与Number 不同。但我不确定如何处理这种情况。如何允许减少(或收集)子类(例如 List<Integer>)的集合?
如果有帮助,这里有一个同样无法编译的更实际的示例:
public static <E> Set<E> reduceSet1(List<? extends Set<E>> sets) {
return sets.stream().reduce(ImmutableSet.<E>of(), (a, b) -> Sets.union(a, b));
}
【问题讨论】:
-
@SotiriosDelimanolis 不是直接的,而是很好的建议!我会发布更多答案。
-
如果您的论点是 BigDecimals 列表,
(Number)0意味着什么? -
@assylias 取决于可能导致问题的累加器函数,但在这种情况下它不应该 - 我想要某种
Number,不一定是BigDecimal。Set示例可能会阐明何时这可能有用。我想返回某种Set,我不在乎它是什么实现。
标签: java generics java-8 java-stream