简体   繁体   English

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

[英]Why is it useful to have null values or null keys in hash maps?

Hashtable does not allow null keys or values, while HashMap allows null values and 1 null key. Hashtable不允许空键或值,而HashMap允许空值和1空键。

Questions: 问题:

  1. Why is this so? 为什么会这样?
  2. How is it useful to have such a key and values in HashMap? 在HashMap中使用这样的键和值有什么用?

1. Why is this so? 1.为什么会这样?

HashMap is newer than Hashtable and fixes some of its limitations. HashMap比Hashtable更新并修复了它的一些限制。

I can only guess what the designers were thinking, but here are my guesses: 我只能猜测设计师的想法,但这是我的猜测:

  • Hashtable calculates a hash for each key by calling hashCode on each key. Hashtable通过在每个键上调用hashCode来计算每个键的哈希值。 This would fail if the key were null, so this could be a reason for disallowing nulls as keys. 如果密钥为空,这将失败,因此这可能是禁止空值作为键的原因。
  • The method Hashtable.get returns null if the key is not present. 如果密钥不存在,方法Hashtable.get将返回null。 If null were a valid value it would be ambiguous as to whether null meant that the key was present but had value null, or if the key was absent. 如果null是一个有效值,那么null是否意味着密钥存在但值为null,或者密钥是否不存在则不明确。 Ambiguity is bad, so this could be a reason for disallowing nulls as values. 歧义是不好的,所以这可能是禁止空值作为值的原因。

However it turns out that sometimes you do actually want to store nulls so the restrictions were removed in HashMap. 然而事实证明,有时你确实想要存储空值,因此在HashMap中删除了限制。 The following warning was also included in the documentation for HashMap.get : HashMap.get的文档中还包含以下警告:

A return value of null does not necessarily indicate that the map contains no mapping for the key; 返回值null不一定表示映射不包含键的映射; it is also possible that the map explicitly maps the key to null. 地图也可能显式地将键映射为null。


2. How is it useful to have such a key and values in HashMap? 2.在HashMap中使用这样的键和值有什么用?

It is useful to explicitly store null to distinguish between a key that you know exists but doesn't have an associated value and a key that doesn't exist. 显式存储null以区分您知道存在但没有关联值的键和不存在的键很有用。 An example is a list of registered users and their birthdays. 一个例子是注册用户及其生日的列表。 If you ask for a specific user's birthday you want to be able to distinguish between that user not existing and the user existing but they haven't entered their birthday. 如果您要求特定用户的生日,您希望能够区分不存在的用户和现有用户,但他们尚未进入他们的生日。

I can't think of any (good) reason for wanting to store null as a key, and in general I'd advise against using null as a key, but presumably there is at least one person somewhere that needs that keys that can be null. 我想不出任何(好的)理由想要将null存储为键,一般来说我建议不要使用null作为键,但可能至少有一个人需要那些键可以是空值。

Well, I think Mark Byers answered perfectly, so just a simple example where null values and keys can be useful: 好吧,我认为Mark Byers回答得非常好,所以只是一个简单的例子,其中null值和键可能很有用:

Imagine you have an expensive function that always returns the same result for the same input. 想象一下,你有一个昂贵的函数,它总是为相同的输入返回相同的结果。 A map is a simple way for caching its results. 地图是缓存其结果的简单方法。 Maybe sometimes the function will return null, but you need to save it anyway, because the execution is expensive. 也许有时函数会返回null,但无论如何你都需要保存它,因为执行起来很昂贵。 So, null values must be stored. 因此,必须存储空值。 The same applies to null key if it's an accepted input for the function. 如果它是函数的可接受输入,则同样适用于null键。

HashTable is very old class , from JDK 1.0.The classes which are in place from JDK 1.0 are called Legacy classes and by default they are synchronized . JDK 1.0开始 ,HashTable是非常老的类。从JDK 1.0到位的类称为Legacy类,默认情况下它们是同步的

To understand this, first of all you need to understand comments written on this class by author. 要理解这一点,首先你需要了解作者在这个课上写的评论。 “This class implements a hashtable, which maps keys to values. “这个类实现了一个哈希表,它将键映射到值。 Any non-null object can be used as a key or as a value. 任何非null对象都可以用作键或值。 To successfully store and retrieve objects from a hashtable, the objects used as keys must implement the hashCode method and the equals method.” 要成功存储和检索哈希表中的对象,用作键的对象必须实现hashCode方法和equals方法。“

HashTable class is implemented on hashing mechanism, means to store any key-value pair, its required hash code of key object. HashTable类是在散列机制上实现的,意味着存储任何键值对,其所需的键对象哈希码。 HashTable calculates a hash for each key by calling hashCode on each key. HashTable通过在每个键上调用hashCode来计算每个键的哈希值。 This would fail If key would be null, it will not be able to give hash for null key, it will throw NullPointerException and similar is the case for value, throwing null if the value is null . 这将失败如果key为null,它将无法为null键提供散列,它将抛出NullPointerException ,类似于value的情况,如果值为null则抛出null

But later on it was realised that null key and value has its own importance, then revised implementations of HashTable were introduced like HashMap which allow one null key and multiple null values. 但后来人们意识到null键和值有其自身的重要性,然后引入了HashTable的修订实现,就像HashMap一样,它允许一个空键和多个空值。

For HashMap, it allows one null key and there is a null check for keys, if the key is null then that element will be stored in a zero location in Entry array. 对于HashMap,它允许一个空键,并且对键进行空检查,如果键为null,则该元素将存储在Entry数组中的零位置。

We cannot have more than one Null key in HashMap because Keys are unique therefor only one Null key and many Null values are allowed. 我们在HashMap中不能有多个Null键,因为Keys是唯一的,因此只允许一个Null键和许多Null值。

USE - Null key we can use for some default value. USE - 我们可以使用Null键作为一些默认值。

Modified and better implementation of HashTable was later introduced as ConcurrentHashMap . 后来,作为ConcurrentHashMap引入了HashTable的修改和更好的实现。

In addition to what answered by Mark Bayers,, Null is considered as data and it has to be stored as a value for further checking. 除了Mark Ba​​yers所回答的问题之外,Null被视为数据,必须将其存储为值以便进一步检查。 In many cases null as value can be used to check if key entry is there but no value is assigned to it, so some action can be taken accordingly. 在许多情况下,null as value可用于检查密钥条目是否存在但没有为其分配值,因此可以采取相应的操作。 This can be done by first checking if key is there, and then getting value. 这可以通过首先检查密钥是否存在,然后获取值来完成。 There is one more case in which just put whatever data is coming(without any check). 还有一个案例,其中只是放入任何数据(没有任何检查)。 All the checks are applied to it after getting it. 获得后,所有检查都会应用到它。

Whereas null as a key, i think can be used to define some default data. 虽然null作为键,但我认为可以用来定义一些默认数据。 Usually null as a key does not make much sense. 通常null作为键没有多大意义。

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

It will make the Map interface easier to use / less verbose. 它将使Map界面更容易使用/更简洁。 null is a legitimate value for reference types. null是引用类型的合法值。 Making the map able to handle null keys and values will eliminate the need for null checking before calling the api. 使映射能够处理null键和值将消除在调用api之前进行空值检查的需要。 So the map api create less "surprises" during runtime. 因此,map api在运行时创建的“惊喜”更少。

For example, it is common that map will be used to categorize a collection of homogeneous objects based a single field. 例如,通常使用map来基于单个字段对同类对象的集合进行分类。 When map is compatible with null, the code will be more concise as it is just a simple loop without any if statement (of course you will need to make sure the collection does not have null elements). 当map与null兼容时,代码将更简洁,因为它只是一个没有任何if语句的简单循环(当然你需要确保集合没有null元素)。 Fewer lines of code with no branch / exception handling will be more likely to be logically correct. 没有分支/异常处理的代码行更少,逻辑上更正确。

On the other hand, not allowing null will not make the map interface better/safer/easier to use. 另一方面,不允许null不会使地图界面更好/更安全/更容易使用。 It is not practical to rely on the map to reject nulls - that means exception will be thrown and you have to catch and handle it. 依靠map拒绝null是不切实际的 - 这意味着抛出异常,你必须捕获并处理它。 Or, to get rid of the exception you will have to ensure nothing is null before calling the map methods - in which case you don't care if map accepts null since you filtered the input anyway. 或者,为了摆脱异常,你必须确保在调用map方法之前没有任何东西 - 在这种情况下你不关心map是否接受null,因为你无论如何都要过滤输入。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM