修复Java Streams中reduce()操作的通配符捕获错误
修复泛型sum方法的通配符捕获错误
问题原因
你的泛型方法中,mapper的返回类型被定义为Function<? super T, ? extends R>,导致map操作后的流类型为Stream<? extends R>。而reduce(R identity, BinaryOperator<R> accumulator)方法要求流的元素类型必须与identity、accumulator的参数类型完全匹配,编译器无法安全地将? extends R类型的元素传递给接受R类型参数的accumulator,因此触发通配符捕获错误。
修复方案
方案一:简化mapper的泛型约束(推荐)
直接将mapper的返回类型约束为R,去掉? extends R,这样map后的流类型为Stream<R>,可以直接匹配reduce的参数要求:
public <T, R> R sum(Collection<T> collection, Predicate<? super T> predicate, Function<? super T, R> mapper, R identity, final BinaryOperator<R> accumulator) { return CollectionUtils.emptyIfNull(collection) .stream() .filter(predicate) .map(mapper) .reduce(identity, accumulator); }
调用示例(与原有逻辑完全兼容):
final BigDecimal spend = sum(forecasts, forecast -> Objects.nonNull(forecast.getPrice()), PartForecastSupplierDto::getPrice, BigDecimal.ZERO, BigDecimal::add);
方案二:保留mapper的子类灵活性
如果需要mapper返回R的子类,可以调整accumulator的类型为BiFunction<R, ? super R, R>,并使用三参数重载的reduce方法,该重载允许接受? super R类型的元素参数:
public <T, R> R sum(Collection<T> collection, Predicate<? super T> predicate, Function<? super T, ? extends R> mapper, R identity, BiFunction<R, ? super R, R> accumulator) { return CollectionUtils.emptyIfNull(collection) .stream() .filter(predicate) .map(mapper) .reduce(identity, accumulator, (a, b) -> accumulator.apply(a, b)); }
第三个参数combiner在串行流中不会被执行,这里直接复用accumulator的逻辑即可,既保留了泛型灵活性,又解决了类型匹配问题。
内容的提问来源于stack exchange,提问作者séan35
相关产品推荐
相关产品推荐

