Является ли HashMap в Java безопасным при столкновении - PullRequest
2 голосов
/ 16 ноября 2009

Я разрабатываю синтаксический анализатор, которому необходимо поместить пары ключ-значение в hashmap.

Но ключ может иметь несколько значений, которые я могу сделать таким образом

HashMap<String,ArrayList<String>>.

Но что произойдет, если количество ключей будет очень большим, и оно начнет совпадать с хеш-кодом другого ключа.

Будет ли это переписывать значение предыдущего ключа?

Ответы [ 5 ]

12 голосов
/ 16 ноября 2009

Если хэш ключа на карте сталкивается с существующим ключом, Карта перегруппирует или сохранит ключи в списке под этим хешем. Никакие ключи не будут перезаписаны другими возникающими ключами, поэтому они будут отсортированы в том же сегменте.

Если несколько потоков используют карту одновременно, вы можете синхронизировать доступ к карте, если она не обрабатывает одновременный доступ. (Некоторые стандартные Карты делают, другие нет. Пакет Java Collections содержит классы-обертки, которые добавляют синхронизацию.)

5 голосов
/ 16 ноября 2009

Во-первых, взгляните на Карта Google Collections Multimap , которая позволит вам назначать несколько значений для каждого ключа без необходимости вручную вести список значений.

Во-вторых, никакие ключи с одинаковым хеш-кодом не будут конфликтовать. Хеш-коды не гарантируются и не должны быть уникальными; HashMap поддерживает «партию» пар ключ / значение для каждого хеш-кода внутри.

4 голосов
/ 16 ноября 2009

HashMap безопасен от столкновений: посмотрите на исходный код для пут:

     /**
      * 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);
     }

Записи таблицы действуют как связанный список. Когда вы помещаете новую запись в ту же корзину, она просто добавляется в связанный список.

2 голосов
/ 06 февраля 2013

Я бы сказал, что столкновение - это не то же самое, что вставка идентичного ключа. Столкновения происходят, когда отдельные ключи хэшируют одно и то же значение. Понятно, что любой, кто реализует интерфейс Map, должен быть оборудован для обработки коллизий. Таким образом, ответ на ваш вопрос заключается в том, что да, HashMap в Java безопасно обрабатывает коллизии.

Однако, если вставлен идентичный ключ, то предыдущее значение, связанное с того же ключа , будет обновлено / перезаписано. Это не считается столкновением как таковым, но прямым ударом по тому, что уже есть.

2 голосов
/ 16 ноября 2009

Он будет перезаписывать значение предыдущего ключа только в том случае, если оно равно предыдущему ключу. Существуют такие методы, как линейное зондирование, перефразирование, сегменты и т. Д., Которые используются в реализациях хэширования, чтобы предотвратить коллизии хеш-кода от перезаписи неравных ключей.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...