#java #hashmap
#java #hashmap
Вопрос:
Я столкнулся с интересной проблемой, в которой, я почти уверен, виноват HashMap
. Рассмотрим следующий отладочный код (AMap — это хэш-карта, ключ — это значение, переданное этому методу)
System.out.println("getBValues - Given: " key);
System.out.println("getBValues - Contains Key: " AMap.containsKey(key));
System.out.println("getBValues - Value: " AMap.get(key));
for(Map.Entry<A,HashSet<B>> entry : AMap.entrySet()) {
System.out.println("getBValues(key) - Equal: " (key.equals(entry.getKey())));
System.out.println("getBValues(key) - HashCode Equal: " (key.hashCode() == entry.getKey().hashCode()));
System.out.println("getBValues(key) - Key: " entry.getKey());
System.out.println("getBValues(key) - Value: " entry.getValue());
}
Теперь в эту карту я вставляю один ключ (канал) и значение. Позже я пытаюсь вернуть значение с помощью get()
и запускаю этот отладочный код, который в моем случае выдает этот результат:
getBValues - Given: Channel(...)
getBValues - Contains Key: false <--- Doesnt contain key?!
getBValues - Value: null <--- Null (bad)
getBValues(key) - Equal: true <--- Given key and AMap key is equal
getBValues(key) - HashCode Equal: true
getBValues(key) - Key: Channel(Same...)
getBValues(key) - Value: [] <--- Not null (This is the expected result)
Как вы можете видеть, извлечение ключа из HashMap напрямую не работает, но при циклическом просмотре я получаю точно такой же ключ, что означает, что он там, с которым его просто нельзя найти get()
. Мой вопрос в том, что могло бы вызвать это? Как get()
не найти существующий ключ?
Я бы привел какой-нибудь пример этого кода, но, похоже, я не могу воспроизвести это независимо.
Любые предложения о том, что может быть причиной этого?
Комментарии:
1. «… что, я почти уверен, является ошибкой HashMap» . Повторяйте за мной. «Ошибка в моем коде». — programmers.stackexchange.com/questions/1785 / …
2. @Stephen Я имел в виду это больше как «Некоторую «особенность» в HashMap, вызывающую это»
Ответ №1:
Бьюсь об заклад, вы неправильно переопределили equals и hashCode в своем классе key Channel. Это бы все объяснило.
Джошуа Блох рассказывает вам, как это правильно сделать в главе 3 «Эффективная Java».
http://java.sun.com/developer/Books/effectivejava/Chapter3.pdf
Комментарии:
1. Я сделал это с Project Lombok, даже специально исключив 2 хэш-набора в классе, которые повлияли бы на равенство.
2. Я не знаю, что такое Project Lombok; я не могу сказать, означает ли это «да, у меня есть правильные equals и реализованный хэш-код». Лучше всего, если ключи тоже будут неизменяемыми. Это верно для вашего канала?
3. В его конкретном тесте hashCode дает одинаковое значение для ключа и сохраненного ключа. Это может быть реализовано неправильно или корректно, но в этом экземпляре это правильно. Клавиша. equals(entry.key) также выдает true. единственная оставшаяся причина, по которой я могу видеть, является ли entry.key.equals (ключ) ложным.
4. Извините, это да. Хэш-код реализован правильно. Посмотрите сюда projectlombok.org/features/EqualsAndHashCode.html
5. Переопределение hashCode помогло мне. Потому что я переопределил только equals ранее, но вы должны переопределить оба, чтобы заставить его работать. Спасибо
Ответ №2:
Из того, что я вижу, мы все еще не исключили, связано ли это с неизменяемостью. Если вы делаете:
aMap.put(key, value);
key.setFieldIncludedInHashCodeAndEquals(25);
тогда вы получите результат выше.
Чтобы исключить это, либо покажите нам больше вашего кода, либо, в цикле for в вашем примере выше, добавьте
System.out.println(aMap.get(entry.getKey()));
Кроме того, используйте отладчик. Таким образом, вы можете увидеть, находится ли ваш объект в правильном сегменте.
Комментарии:
1. Хм … это дало мне нулевое значение. Я предполагаю, что хэш-код меняется после его добавления. Я посмотрю, смогу ли я обновить свой код до чего-то работоспособного.
2. Итак, изменилось ли какое-либо поле, являющееся частью hashCode или equals в объекте, который вы сохранили как ключ в aMap, после добавления объекта на вашу карту?
3. Вот почему ключи в картах должны быть неизменяемыми.