это - перебор map java




Бесконечный цикл при использовании ключа несколько раз в HashMap (4)

HashMap попадает в бесконечный цикл.

Я не могу понять, почему HashMap выдает ошибку stackoverflow, когда один и тот же ключ используется несколько раз.

Код:

import java.util.HashMap;

public class Test {
    public static void main(String[] args) {
        HashMap hm = new HashMap();

        hm.put(hm, "1");
        hm.put(hm, "2");
    }
} 

Ошибка:

Исключение в потоке "main" java.lang.StackOverflowError


Вы используете в качестве ключа сам хэш-файл -> это означает, что рекурсия -> нет условия выхода -> .

Просто используйте ключ (Long, String, Object все, что вы хотите).

И да, как ищите Addo, добавьте типы с <> скобками.


Проблема заключается не в том, что хеш-карта взрывает стек для «того же ключа», который вводится дважды, а потому, что ваш конкретный выбор ключа карты. Вы добавляете карту хеша к себе.

Чтобы объяснить лучше - часть контракта на Карту заключается в том, что ключи не должны меняться так, чтобы они влияли на их методы равенства (или хэш-код, если на то пошло).

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

Для получения дополнительной информации это от док-станции JDK для интерфейса карты:

Примечание. Следует проявлять большую осторожность, если изменяемые объекты используются в качестве ключей карты. Поведение карты не указывается, если значение объекта изменяется таким образом, который влияет на равные сравнения, пока объект является ключом на карте. Частным случаем этого запрета является то, что карта не может содержать себя как ключ. Хотя допустимо, чтобы карта содержала себя как значение, рекомендуется проявлять особую осторожность: методы equals и hashCode более не определены на такой карте.


Невозможно добавить к самой Map в качестве ключа. Из javadoc :

Частным случаем этого запрета является то, что карта не может содержать себя как ключ .

Проблема в том, что вы используете как ключ не стандартный объект (любой объект с хорошо определенными методами equals и hashCode , который не является самой картой), а сама карта.

Проблема заключается в том, как вычисляется hashCode - HashMap :

public int hashCode() {
   int h = 0;
   Iterator<Entry<K,V>> i = entrySet().iterator();
   while (i.hasNext())
       h += i.next().hashCode();
   return h;
}

Как вы можете видеть, для вычисления хэш-кода карты он выполняет итерацию по всем элементам карты. И для каждого элемента он вычисляет hashCode. Поскольку единственным элементом карты является ключ, является сама карта, она становится источником рекурсии.

Замена карты другим объектом, который может использоваться как ключ (с четко определенными equals и hashCode ), будет работать:

import java.util.HashMap;

 public class Test {
   public static void main(String[] args) {
     HashMap hm = new HashMap();

     String key = "k1";
     hm.put(key, "1");
     hm.put(key, "2");
   }
} 

Вы используете одно и то же имя объекта как ключ, так что это бесконечный цикл.

поэтому это переполнение стека.





stack-overflow