1-Collectors.toMap无法正确处理null值

Collectors.toMap在在处理null值时,会出现NullPointerException

示例

DishCategoryAllPO d1 = new DishCategoryAllPO();
d1.setDishId(11111);
d1.setPrimaryLabel("11111");

DishCategoryAllPO d2 = new DishCategoryAllPO();
d2.setDishId(11111);

DishCategoryAllPO d3 = new DishCategoryAllPO();
d3.setDishId(22222);

DishCategoryAllPO d4 = new DishCategoryAllPO();
d4.setDishId(22222);
d4.setPrimaryLabel("22222");

DishCategoryAllPO d5 = new DishCategoryAllPO();
d5.setDishId(33333);

List<DishCategoryAllPO> list = Arrays.asList(d1, d2, d3, d4, d5);

Map<Integer, String> map = list.stream().collect(Collectors.toMap(DishCategoryAllPO::getDishId, DishCategoryAllPO::getPrimaryLabel,
        (existing, replacement) -> existing));

map.forEach((k,v) -> System.out.println(k+" "+v));

在这个例子中,d2和d5对象的primaryLabel属性没有被设置,即它们为null。当尝试将这些null值插入到Map中时,就会抛出NullPointerException。

原因
当尝试将null值插入到Map中时抛出NullPointerException的原因涉及到Jav 8 Collectors.toMap()方法的内部实现。具体来说:

  • Collectors.toMap()内部使用HashMap来存储结果。
  • 在Java 8中,HashMap的merge()方法被用来处理键值对的插入和合并。
  • merge()方法在处理值为null的情况时有一个特殊的逻辑:如果新值为null,它会尝试删除已存在的键值对。
  • 然而,在Collectors.toMap()的实现中,merge()方法被调用时假设了值永远不会为null。
  • 当遇到null值时,merge()方法会尝试对null执行操作,从而导致NullPointerException。


经验教训

  • 这个问题在Java 9中得到了修复,通过改变Collectors.toMap()的实现来正确处理null值。但在Java 8中,这个问题仍然存在。

  • Map<Integer, String> map = list.stream()
      .collect(Collectors.toMap(DishCategoryAllPO::getDishId, 
          dish -> dish.getPrimaryLabel() != null ? dish.getPrimaryLabel() : "默认值", // 提供默认值
          (existing, replacement) -> existing));
    
  • Map<Integer, String> map = list.stream()
      .filter(dish -> dish.getPrimaryLabel() != null) // 过滤掉primaryLabel为null的元素
      .collect(Collectors.toMap(DishCategoryAllPO::getDishId, DishCategoryAllPO::getPrimaryLabel,
          (existing, replacement) -> existing));
    
posted @ 2024-11-05 11:22  言思宁  阅读(24)  评论(0编辑  收藏  举报