为什么在哈希映射中使用空值或空键是有用的?

时间:2010-09-01 20:43:05

标签: java hashmap

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

问题:

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

6 个答案:

答案 0 :(得分:41)

  

1。为什么会这样?

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

我只能猜测设计师在想什么,但这是我的猜测:

  • Hashtable通过在每个键上调用hashCode来计算每个键的哈希值。如果密钥为空,这将失败,因此这可能是禁止空值作为键的原因。
  • 如果密钥不存在,方法Hashtable.get将返回null。如果null是一个有效值,那么null是否意味着密钥存在但值为null,或者密钥是否不存在则不明确。歧义是不好的,所以这可能是禁止空值作为值的原因。

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

  

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


  

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

显式存储null以区分您知道存在但未具有关联值的密钥和不存在的密钥非常有用。一个例子是注册用户及其生日的列表。如果您要求特定用户的生日,您希望能够区分不存在的用户和现有的用户,但他们尚未进入他们的生日。

我想不出任何(好)理由想要将null存储为键,一般来说我建议不要使用null作为键,但可能至少有一个人需要那个键可以为空。

答案 1 :(得分:13)

嗯,我认为Mark Byers完美回答,所以只是一个简单的例子,其中空值和键可能有用:

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

答案 2 :(得分:3)

HashTable是一个非常古老的类,来自JDK 1.0。来自 JDK 1.0 的类称为 Legacy 类,默认情况下它们是 synchronized < /强>

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

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

但后来人们意识到null键和值有其自身的重要性,然后引入了HashTable的修订实现,就像HashMap一样,允许一个空键和多个空值。

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

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

USE - 我们可以使用Null键作为默认值。

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

答案 3 :(得分:2)

除了Mark Ba​​yers的回答, Null被视为数据,必须将其存储为值以便进一步检查。在许多情况下,null as value可用于检查密钥条目是否存在但没有为其分配值,因此可以采取相应的操作。这可以通过首先检查密钥是否存在,然后获取值来完成。 还有一个案例,其中只是放入任何数据(没有任何检查)。获得后,所有检查都会应用到它。

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

答案 4 :(得分:1)

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

答案 5 :(得分:0)

它将使Map界面更容易使用/更简洁。 null是引用类型的合法值。使映射能够处理null键和值将消除在调用api之前进行空值检查的需要。因此,map api在运行时会产生较少的“惊喜”。

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

另一方面,不允许null不会使地图界面更好/更安全/更容易使用。依靠map拒绝null是不切实际的 - 这意味着抛出异常,你必须捕获并处理它。或者,为了摆脱异常,你必须确保在调用map方法之前没有任何东西 - 在这种情况下你不关心map是否接受null,因为你无论如何都过滤了输入。