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

使用Collectors.toMap去重合并时触发NullPointerException问题

问题:创建ProductKey到ProductDetail的Map时触发NullPointerException

我正尝试为需要添加ProductDetail的Products列表创建一个Map<ProductKey, ProductDetail>。ProductDetail对象通过ProductDetailLookUpService从数据库读取(因涉及内部信息未展示该服务)。产品可能存在或不存在ProductDetail,同类产品可能共享同一ProductDetail。但在执行合并操作时触发了NullPointerException。


相关类定义

@Data
static class ProductKey{
    @EqualsAndHashCode.Include
    private Long productCode;
    @EqualsAndHashCode.Include
    private Long productDetailCode;
}

@Data
class Product {
    @EqualsAndHashCode.Include
    private ProductKey productKey;
    @EqualsAndHashCode.Include
    private ProductDetail productDetail;
}

@Data
class ProductDetail{
    @EqualsAndHashCode.Include
    private Long productCode;
    private String description;
    private BigDecimal price;
    private String category;
}

public static Optional<ProductKey> findProductKey(Long productCode, List<ProductKey> productKeys) {
    return  productKeys.stream()
        .filter(productKey -> productCode.equals(productKey.getProductCode()))
        .takeWhile(productKey -> productKey != null)
        .findFirst();
}

报错信息

java.lang.NullPointerException: null
at java.base/java.util.HashMap.merge(HashMap.java:1267) ~[na:na]
at java.base/java.util.stream.Collectors.lambda$toMap$68(Collectors.java:1658) ~[na:na]
at java.base/java.util.stream.ReduceOps$3ReducingSink.accept(ReduceOps.java:169) ~[na:na]
at java.base/java.util.stream.ReferencePipeline$2$1.accept(ReferencePipeline.java:177) ~[na:na]
at java.base/java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:195) ~[na:na]
at java.base/java.util.stream.ReferencePipeline$2$1.accept(ReferencePipeline.java:177) ~[na:na]

填充Map的代码(已修改但仍报错)

我原本添加了过滤器,确保productDetailMap包含匹配的productKey.getProductCode(),以为能排除无匹配productCode的产品,合并时不会出现null,但实际仍报错:

List<ProductKey> productKeyList = // 初始化列表
        
Map<Long, ProductDetail> productDetailMap = // 初始化map
        
Map<ProductKey, ProductDetail> prodDetailByKey = productKeyList.stream()
    .map(productKey -> findProductKey(productKey.getProductCode(), productKeyList))
    .filter(Optional::isPresent)
    .map(Optional::get)
    .filter(productKey -> productDetailMap.values().contains(productKey.getProductCode()))
    .collect(Collectors.toMap(
        Function.identity(),
        productKey -> productDetailMap.get(productKey.getProductCode()),
        (left, right) -> left // 预防productKeyList中出现重复元素
    ));

补充操作建议

  • 将Map中的ProductDetail设置到对应Product时,使用Iterable.forEach()比stream更合适:
List<Product> products = service.readProducts();
    
products.forEach(product -> 
    product.setProductDetail(prodDetailByKey.get(product.getProductKey()))
);
  • 移除Map中的null值可使用以下方式:
productDetailMap.values().removeIf(Objects::isNull);

内容的提问来源于stack exchange,提问作者BreenDeen

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.13 09:20:42