Java碰撞中的HashMap是否安全

时间:2009-11-15 21:46:23

标签: java collections hashmap

我正在开发一个需要在hashmap中放置键值对的解析器。

但是一个键可以有多个值,我可以这样做

HashMap<String,ArrayList<String>>

但是如果密钥数量非常大并且它开始与其他密钥的哈希码匹配,会发生什么。

这会重写上一个键的值吗?

5 个答案:

答案 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可以安全地处理冲突。

但是,如果插入了相同的密钥,则将更新/覆盖与完全相同的密钥关联的先前值。这本身并不算是碰撞,而是直接破坏已经存在的东西。