Consider the following Code :
考虑以下代码:
import java.util.*;
class Employee {
String name;
public Employee(String nm) {
this.name=nm;
}
}
public class HashMapKeyNullValue {
Employee e1;
public void display(){
Employee e2=null;
Map map=new HashMap();
map.put(e2, "25");
System.out.println("Getting the Value When e2 is set as KEY");
System.out.println("e2 : "+map.get(e2));
System.out.println("e1 : "+map.get(e1));
System.out.println("null : "+map.get(null));
map.put(e1, "");
System.out.println("Getting the Value when e1 is set as KEY");
System.out.println("e2 : "+map.get(e2));
System.out.println("e1 : "+map.get(e1));
System.out.println("null : "+map.get(null));
map.put(null, null); // null as key and null as value
System.out.println("Getting the Value when setting null as KEY and null as value");
System.out.println("e2 : "+map.get(e2));
System.out.println("e1 : "+map.get(e1));
System.out.println("null : "+map.get(null));
map.put(null, "30");
System.out.println("Getting the Value when setting only null as KEY");
System.out.println("e2 : "+map.get(e2));
System.out.println("e1 : "+map.get(e1));
System.out.println("null : "+map.get(null));
}
public static void main(String[] args) {
new HashMapKeyNullValue().display();
}
}
The Output of program is :
程序的输出为:
Getting the Value When e2 is set as KEY
e2 : 25
e1 : 25
null : 25
Getting the Value when e1 is set as KEY
e2 :
e1 :
null :
Getting the Value when setting null as KEY and null as value
e2 : null
e1 : null
null : null
Getting the Value when setting only null as KEY
e2 : 30
e1 : 30
null : 30
Here how e1, e2, and null
as keys are related to each other. Is all three are assigned to same hashcode ? If yes, WHY ?
这里,e1, e2和null作为键是相互关联的。所有三个都被分配给相同的hashcode吗?如果是,为什么?
Since all three seems to be look different the change in one value changes the other. Does it mean that only one entry for key is being made into HashMap
either e1, e2, or null
beacause all treated to be like the same key.
因为这三个看起来都是不同的,一个值的变化会改变另一个值。这是否意味着只有一个键的条目被做成了HashMap,要么e1, e2,要么为空,因为所有处理的都是相同的键。
5 个解决方案
#1
21
HashMap
does not call hashcode when null is passed as key and null Key is handled as special case.
HashMap在将null作为key和null键作为特殊情况处理时不调用hashcode。
Put Method
HashMap
puts null key in bucket 0 and maps null as key to passed value. it does it by linked list data structure it uses internally.
HashMap将null键放入bucket 0中,并将null作为传递值的键。它使用内部的链表数据结构来实现。
Linked list data structure used by HashMap
(a static class in HashMap.java
)
HashMap使用的链表数据结构(HashMap.java中的静态类)
static class Entry<K,V> implements Map.Entry<K,V> {
final K key;
V value;
Entry<K,V> next;
final int hash;
}
In Entry class the K is set to null and value mapped to value passed in put method.
在Entry类中,K被设置为null,并将值映射到通过put方法传递的值。
Get Method
While in Hashmap
get method the checks if key is passed as null. Search Value for null key in bucket 0.
当在Hashmap中获取方法时,如果键被传递为null。在bucket 0中搜索null键的值。
Hence there can only be one null key in one hashmap
object.
因此,在一个hashmap对象中只能有一个空键。
#2
4
If you pass null
as map key, it will go to 0 bucket
. All values of null key will go there. That is why it returns same value, cause all keys you are providing are null
and are in the same bucket of your HashMap.
如果您传递null作为映射键,它将会变为0个bucket。空键的所有值都将在那里。这就是为什么它返回相同的值,因为您提供的所有键都是null,并且在HashMap的同一个bucket中。
#3
2
Incase of null key , Hashmap implementation consider it as special case and doesnot call hashCode method instead it stores Entry object to 0 bucket location.
在null键的情况下,Hashmap实现将其视为特殊情况,不调用hashCode方法,而是将条目对象存储到0 bucket位置。
#4
1
A HashMap can only store one value per key. If you want to store more values, you have to use a MultivalueHashMap (Google Guava and Apache Commons Collections contain implementations of such a map).
HashMap只能存储每个键的一个值。如果您想存储更多的值,则必须使用MultivalueHashMap(谷歌Guava和Apache Commons集合包含这样的映射的实现)。
e1 and e2 have the value null, since you don't assign any object to them. So if you use those variables, the key of that map entry is also null, which leads to your result. Null doesn't have any hashcode, but is tolerated as key in the HashMap (there are other Map implementations which don't allow Null as key).
e1和e2的值为null,因为您没有为它们分配任何对象。因此,如果使用这些变量,映射条目的键也是null,这将导致结果。Null没有任何hashcode,但可以作为HashMap中的键(还有其他映射实现,不允许Null作为键)。
#5
1
When you put NULL to HashMap there is special check if you are trying to put NULL as key (called putForNullKey()). It is special case and works not like you are trying to put some object which is not null, and as you may see it even doesn't go to hash calculation.
当您将NULL映射到HashMap时,如果您试图将NULL作为键(称为putForNullKey()),则会有特殊的检查。它是特殊情况,不像你试图放置一些非空的对象,你可能会看到,它甚至不会被哈希计算。
public V put(K key, V value) {
if (table == EMPTY_TABLE) {
inflateTable(threshold);
}
if (key == null)
return putForNullKey(value);
int hash = hash(key);
int i = indexFor(hash, table.length);
for (Entry<K,V> e = table[i]; e != null; e = e.next) {
Object k;
if (e.hash == hash && ((k = e.key) == key || key.equals(k))) {
V oldValue = e.value;
e.value = value;
e.recordAccess(this);
return oldValue;
}
}
modCount++;
addEntry(hash, key, value, i);
return null;
}
private V putForNullKey(V value) {
for (Entry<K,V> e = table[0]; e != null; e = e.next) {
if (e.key == null) {
V oldValue = e.value;
e.value = value;
e.recordAccess(this);
return oldValue;
}
}
modCount++;
addEntry(0, null, value, 0);
return null;
}
#1
21
HashMap
does not call hashcode when null is passed as key and null Key is handled as special case.
HashMap在将null作为key和null键作为特殊情况处理时不调用hashcode。
Put Method
HashMap
puts null key in bucket 0 and maps null as key to passed value. it does it by linked list data structure it uses internally.
HashMap将null键放入bucket 0中,并将null作为传递值的键。它使用内部的链表数据结构来实现。
Linked list data structure used by HashMap
(a static class in HashMap.java
)
HashMap使用的链表数据结构(HashMap.java中的静态类)
static class Entry<K,V> implements Map.Entry<K,V> {
final K key;
V value;
Entry<K,V> next;
final int hash;
}
In Entry class the K is set to null and value mapped to value passed in put method.
在Entry类中,K被设置为null,并将值映射到通过put方法传递的值。
Get Method
While in Hashmap
get method the checks if key is passed as null. Search Value for null key in bucket 0.
当在Hashmap中获取方法时,如果键被传递为null。在bucket 0中搜索null键的值。
Hence there can only be one null key in one hashmap
object.
因此,在一个hashmap对象中只能有一个空键。
#2
4
If you pass null
as map key, it will go to 0 bucket
. All values of null key will go there. That is why it returns same value, cause all keys you are providing are null
and are in the same bucket of your HashMap.
如果您传递null作为映射键,它将会变为0个bucket。空键的所有值都将在那里。这就是为什么它返回相同的值,因为您提供的所有键都是null,并且在HashMap的同一个bucket中。
#3
2
Incase of null key , Hashmap implementation consider it as special case and doesnot call hashCode method instead it stores Entry object to 0 bucket location.
在null键的情况下,Hashmap实现将其视为特殊情况,不调用hashCode方法,而是将条目对象存储到0 bucket位置。
#4
1
A HashMap can only store one value per key. If you want to store more values, you have to use a MultivalueHashMap (Google Guava and Apache Commons Collections contain implementations of such a map).
HashMap只能存储每个键的一个值。如果您想存储更多的值,则必须使用MultivalueHashMap(谷歌Guava和Apache Commons集合包含这样的映射的实现)。
e1 and e2 have the value null, since you don't assign any object to them. So if you use those variables, the key of that map entry is also null, which leads to your result. Null doesn't have any hashcode, but is tolerated as key in the HashMap (there are other Map implementations which don't allow Null as key).
e1和e2的值为null,因为您没有为它们分配任何对象。因此,如果使用这些变量,映射条目的键也是null,这将导致结果。Null没有任何hashcode,但可以作为HashMap中的键(还有其他映射实现,不允许Null作为键)。
#5
1
When you put NULL to HashMap there is special check if you are trying to put NULL as key (called putForNullKey()). It is special case and works not like you are trying to put some object which is not null, and as you may see it even doesn't go to hash calculation.
当您将NULL映射到HashMap时,如果您试图将NULL作为键(称为putForNullKey()),则会有特殊的检查。它是特殊情况,不像你试图放置一些非空的对象,你可能会看到,它甚至不会被哈希计算。
public V put(K key, V value) {
if (table == EMPTY_TABLE) {
inflateTable(threshold);
}
if (key == null)
return putForNullKey(value);
int hash = hash(key);
int i = indexFor(hash, table.length);
for (Entry<K,V> e = table[i]; e != null; e = e.next) {
Object k;
if (e.hash == hash && ((k = e.key) == key || key.equals(k))) {
V oldValue = e.value;
e.value = value;
e.recordAccess(this);
return oldValue;
}
}
modCount++;
addEntry(hash, key, value, i);
return null;
}
private V putForNullKey(V value) {
for (Entry<K,V> e = table[0]; e != null; e = e.next) {
if (e.key == null) {
V oldValue = e.value;
e.value = value;
e.recordAccess(this);
return oldValue;
}
}
modCount++;
addEntry(0, null, value, 0);
return null;
}