【问题标题】:Why is it useful to have null values or null keys in hash maps?为什么在哈希映射中有空值或空键很有用?
【发布时间】:2011-04-07 00:37:24
【问题描述】:

Hashtable 不允许空键或空值,而HashMap 允许空值和 1 个空键。

问题:

  1. 为什么会这样?
  2. 在 HashMap 中有这样的键和值有什么用处?

【问题讨论】:

  • “重要性”是什么意思?
  • @Michael Mrozek:可能很重要。如果您将其视为“为什么null 足够重要以具有这些特殊名称”,那么“重要性”在这里不是一个可怕的词。

标签: java hashmap


【解决方案1】:

1。为什么会这样?

HashMap 比 Hashtable 更新,并修复了它的一些限制。

我只能猜测设计师的想法,但以下是我的猜测:

  • Hashtable 通过在每个键上调用hashCode 来计算每个键的哈希值。如果键为空,这将失败,因此这可能是不允许空作为键的原因。
  • 如果键不存在,Hashtable.get 方法将返回 null。如果 null 是一个有效值,那么 null 是否意味着键存在但值为 null,或者该键不存在,这将是模棱两可的。模棱两可很糟糕,因此这可能是不允许将空值作为值的原因。

但事实证明,有时您确实想要存储空值,因此在 HashMap 中取消了限制。 HashMap.get 的文档中还包含以下警告:

返回值为 null 并不一定表示该映射不包含该键的映射;也有可能映射显式地将键映射到 null。


2。在 HashMap 中有这样的键和值有什么用?

显式存储 null 以区分您知道存在但没有关联值的键和不存在的键是有用的。一个例子是注册用户列表和他们的生日。如果您询问特定用户的生日,您希望能够区分该用户不存在和存在但未输入生日的用户。

我想不出任何(好的)理由想要将 null 存储为密钥,一般而言,我建议不要使用 null 作为密钥,但大概在某个地方至少有一个人需要该密钥可以为空。

【讨论】:

  • 就个人而言,我认为null 值没有任何意义。他们强迫你查询地图两次。您必须使用map.get( )map.containsKey() 来确定系统已知该密钥,而不是单个map.get()。难怪null 值在Map 接口的许多新特化中是不允许的。
  • 假设您正在计算披萨价格。可以使用映射来映射顶部和附加成本;您可以将 null 映射到零,并且逻辑比特殊情况下的无浇头比萨饼更简单。这当然不是一个很好的例子,但我认为它暗示了一个合理的理由可能是什么样的。
  • 关于空值有效性的很好的解释。
  • 你说“显式存储null来区分...还是您正在考虑调用另一种方法来进行检查?
【解决方案2】:

嗯,我认为 Mark Byers 回答得很好,所以只是一个简单的例子,其中 null 值和键很有用:

假设您有一个昂贵的函数,它总是为相同的输入返回相同的结果。地图是一种缓存其结果的简单方法。也许有时函数会返回 null,但无论如何你都需要保存它,因为执行成本很高。因此,必须存储空值。如果它是函数的可接受输入,这同样适用于 null 键。

【讨论】:

    【解决方案3】:

    HashTable 是一个非常古老的类,来自 JDK 1.0。来自 JDK 1.0 的类被称为 Legacy 类,默认情况下它们是同步。

    要理解这一点,首先你需要理解作者在这个类上写的cmets。 “这个类实现了一个哈希表,它将键映射到值。任何非空对象都可以用作键或值。要成功地从哈希表中存储和检索对象,用作键的对象必须实现 hashCode 方法和 equals 方法。”

    HashTable类是在散列机制上实现的,意思是存储任意键值对,其所需要的键对象的散列码。 HashTable 通过在每个键上调用 hashCode 来计算每个键的哈希值。这将失败如果 key 为 null,它将无法为 null key 提供哈希,它将抛出 NullPointerException 和 value 的情况类似,如果 value 为 null,则抛出 null.

    但后来意识到空键和空值有其重要性,于是引入了HashTable的修改实现,例如允许一个空键和多个空值的HashMap。

    对于HashMap,它允许一个空键,并且对键进行空检查,如果该键为空,则该元素将存储在Entry数组中的零位置。

    我们在 HashMap 中不能有多个 Null 键,因为键是唯一的,因此只允许一个 Null 键和多个 Null 值。

    USE - 我们可以将 Null 键用于一些默认值。

    HashTable 的改进和更好的实现后来被引入为 ConcurrentHashMap

    【讨论】:

      【解决方案4】:

      除了 Mark Ba​​yers 的回答之外, Null 被视为数据,必须将其存储为值以供进一步检查。在许多情况下,可以使用 null 作为值来检查是否存在键条目但没有为其分配值,因此可以相应地采取一些措施。这可以通过首先检查 key 是否存在,然后获取 value 来完成。 还有另一种情况,只需输入即将到来的任何数据(无需任何检查)。得到它后,所有的检查都应用到它。

      而 null 作为键,我认为可以用来定义一些默认数据。通常 null 作为键没有多大意义。

      【讨论】:

        【解决方案5】:

        Sir HashMap 也在内部使用 hashCode() 方法在 HashMap 中插入元素,所以我认为这不是“为什么 HashTable 允许空键”的正确原因

        【讨论】:

        • 但是 hashmap 检查 key==null 是否返回 hashval 为 0。
        【解决方案6】:

        这将使地图界面更易于使用/不那么冗长。 null 是引用类型的合法值。使映射能够处理空键和值将消除调用 api 之前对空值检查的需要。所以地图 api 在运行时创造的“惊喜”更少。

        例如,通常使用地图对基于单个字段的同类对象集合进行分类。当 map 与 null 兼容时,代码会更简洁,因为它只是一个没有任何 if 语句的简单循环(当然你需要确保集合没有 null 元素)。没有分支/异常处理的代码行越少,逻辑上正确的可能性就越大。

        另一方面,不允许 null 不会使地图界面更好/更安全/更易于使用。依靠映射来拒绝空值是不切实际的——这意味着将抛出异常,您必须捕获并处理它。或者,要消除异常,您必须在调用 map 方法之前确保没有任何内容为 null - 在这种情况下,您不必关心 map 是否接受 null,因为您过滤了输入。

        【讨论】:

          猜你喜欢
          • 2023-03-11
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2011-06-02
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2011-08-03
          相关资源
          最近更新 更多