事实上,它本可以形成一个链表。只是Map
合同要求它替换条目:
V put(K key, V value)
将指定值与此映射中的指定键关联(可选操作)。如果映射先前包含键的映射,则旧值将替换为指定值。(当且仅当 m.containsKey(k) 返回 true 时,映射 m 被称为包含键 k 的映射。)
http://docs.oracle.com/javase/6/docs/api/java/util/Map.html
对于存储值列表的地图,它需要是一个Multimap
. 这是谷歌的:http: //google-collections.googlecode.com/svn/trunk/javadoc/com/google/common/collect/Multimap.html
类似于 Map 的集合,但可以将多个值与单个键相关联。如果您使用相同的键但值不同的两次调用 put(K, V),则多重映射包含从键到两个值的映射。
编辑:碰撞解决
这有点不同。当两个不同的键碰巧具有相同的哈希码,或者具有不同哈希码的两个键碰巧映射到底层数组中的同一个桶时,就会发生冲突。
考虑HashMap
's source (点点滴滴):
public V put(K key, V value) {
int hash = hash(key.hashCode());
int i = indexFor(hash, table.length);
// i is the index where we want to insert the new element
addEntry(hash, key, value, i);
return null;
}
void addEntry(int hash, K key, V value, int bucketIndex) {
// take the entry that's already in that bucket
Entry<K,V> e = table[bucketIndex];
// and create a new one that points to the old one = linked list
table[bucketIndex] = new Entry<>(hash, key, value, e);
}
对于那些好奇这个Entry
类如何HashMap
表现得像一个列表的人,事实证明它HashMap
定义了自己的静态Entry
类,它实现了Map.Entry
. 您可以通过查看源代码自己了解:
HashMap 的 GrepCode