You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

修复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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.20 18:16:03