我正在开发一个需要在hashmap中放置键值对的解析器。
但是一个键可以有多个值,我可以这样做
HashMap<String,ArrayList<String>>
。
但是如果密钥数量非常大并且它开始与其他密钥的哈希码匹配,会发生什么。
这会重写上一个键的值吗?
答案 0 :(得分:12)
如果地图中的键的哈希与现有键冲突,则Map将重新排列或将键保留在该哈希下的列表中。没有密钥会被其他密钥覆盖,因此会在同一个存储桶中进行排序。
如果多个线程同时使用映射,则可能希望在不处理并发访问时同步对映射的访问。 (某些标准映射可以执行,其他则不执行.Java Collections包确实包含添加同步的包装类。)
答案 1 :(得分:5)
首先,看看Google Collections Multimap,它可以让您为每个键分配多个值,而无需手动维护值列表。
其次,没有 - 具有相同哈希码的密钥不会发生冲突。哈希码不保证或要求是唯一的; HashMap在内部为每个哈希代码维护一个键/值对“桶”。
答案 2 :(得分:4)
HashMap是防碰撞的:查看the sourcecode以获取:
/**
* Associates the specified value with the specified key in this map.
* If the map previously contained a mapping for the key, the old
* value is replaced.
*
* @param key key with which the specified value is to be associated
* @param value value to be associated with the specified key
* @return the previous value associated with <tt>key</tt>, or
* <tt>null</tt> if there was no mapping for <tt>key</tt>.
* (A <tt>null</tt> return can also indicate that
* previously associated <tt>null</tt> with <tt>key</tt>.)
*/
public V put(K key, V value) {
if (key == null)
return putForNullKey(value);
int hash = hash(key.hashCode());
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;
}
和
/**
* Adds a new entry with the specified key, value and hash code to
* the specified bucket. It is the responsibility of this
* method to resize the table if appropriate.
*
* Subclass overrides this to alter the behavior of put method.
*/
void addEntry(int hash, K key, V value, int bucketIndex) {
Entry<K,V> e = table[bucketIndex];
table[bucketIndex] = new Entry<K,V>(hash, key, value, e);
if (size++ >= threshold)
resize(2 * table.length);
}
表格的条目就像一个链表。当您将新条目放入同一个存储桶时,它只会添加到链接列表中。
答案 3 :(得分:2)
如果它等于前一个键,它将只覆盖前一个键的值。有一些方法,如线性探测,重新散列,存储桶等,它们在散列实现中用于防止哈希码冲突覆盖不等密钥。
答案 4 :(得分:2)
我认为碰撞与插入相同的密钥不同。当单独的键散列到相同的值时发生冲突。可以理解的是,任何实现Map接口的人都应该具备处理冲突的能力。因此,您的问题的答案是肯定的,Java中的HashMap可以安全地处理冲突。
但是,如果插入了相同的密钥,则将更新/覆盖与完全相同的密钥关联的先前值。这本身并不算是碰撞,而是直接破坏已经存在的东西。