java中使用stream流的Collectors.toMap()报空指针异常

771 阅读3分钟

**问题背景:

​    ​在将一个list集合通过stream流的Collectors.toMap()方法转换成map集合的时候,报空指针异常​。

​产生原因:

​    ​Collectors.toMap()的key和value  都不能为null。

​    ​自己仅判断了key不能为​null,没有判断value,导致上述现象产生。

​为什么要key和value都不为null?

在Java中,Map 接口及其常见实现(如 HashMapLinkedHashMap 等)对键和值有一些基本的要求。特别是,大多数 Map 实现不允许键为 null,并且默认情况下也不允许值为 null。这是为了避免在处理键值对时出现意外的空指针异常和其他潜在问题。下面详细解释为什么键和值不能为 null

为什么键不能为 null

  1. 唯一性Map 的键必须是唯一的。如果允许键为 null,那么多个键都为 null 的条目将无法区分,这会导致混乱。

  2. 查找效率Map 内部通常使用哈希表或其他数据结构来存储键值对。如果键为 null,哈希表的查找和插入操作可能会变得复杂,影响性能。例如,HashMap 在处理 null 键时需要特殊处理,增加了代码的复杂性。

  3. 一致性:大多数 Map 实现(如 HashMap)不允许键为 null,以保持一致的行为。如果你在 Map 中插入了一个键为 null 的条目,后续的操作可能会抛出 NullPointerException

为什么值不能为 null

  1. 默认行为:虽然某些 Map 实现(如 HashMap)允许值为 null,但这并不是一个推荐的做法。如果值为 null,可能会导致在获取值时出现混淆,因为你无法区分某个键是否存在但值为 null,还是该键根本不存在。

  2. 一致性:为了保持代码的一致性和可读性,通常建议避免在 Map 中存储值为 null 的条目。如果需要表示某个键没有对应的值,可以使用 Optional 类或其他方式来表示。

  3. API 设计Collectors.toMap 方法的设计者选择不允许值为 null,以确保生成的 Map 是一致的和可靠的。如果允许值为 null,可能会导致后续操作中的空指针异常。

Collectors.toMap 的要求

Collectors.toMap 方法在内部会使用 Map 来存储键值对。如果键或值为 null,它会抛出 NullPointerException,以防止上述问题的发生。具体来说:

  • 键不能为 null:如果键为 nulltoMap 方法会立即抛出 NullPointerException

  • 值不能为 null:虽然某些 Map 实现允许值为 null,但 toMap 方法默认情况下不允许值为 null,除非你提供了一个特殊的合并函数来处理这种情况。

如何避免空指针异常

为了避免在使用 Collectors.toMap 时出现空指针异常,可以采取以下措施:

  1. 过滤掉无效数据

    
    .filter(order -> order.getMerchantId() != null && order.getMerchantName() != null)
    
    
  2. 使用 Objects.requireNonNull

    
    .collect(Collectors.toMap(
    
        order -> Objects.requireNonNull(order.getMerchantId(), "Merchant ID cannot be null"),
    
        order -> Objects.requireNonNull(order.getMerchantName(), "Merchant Name cannot be null"),
    
        (oldValue, newValue) -> oldValue
    
    ))
    
    
  3. 提供默认值

    如果你希望在值为 null 时提供一个默认值,可以这样做:

    
    .collect(Collectors.toMap(
    
        Order::getMerchantId,
    
        order -> order.getMerchantName() == null ? "Default Merchant Name" : order.getMerchantName(),
    
        (oldValue, newValue) -> oldValue
    
    ))
    
    

通过这些措施,你可以确保在使用 Collectors.toMap 时不会因为键或值为 null 而抛出空指针异常。这样可以提高代码的健壮性和可靠性。**