Это очень классический вопрос в Java, и его часто задают во время интервью. Фактически, многие книги или статьи упоминали, что вам нужно перегружать методы HashCode () и Equals (), чтобы реализовать поиск пользовательских ключей в HashMap. Тем не менее, кажется, что немногие статьи говорят о том, почему вам нужно это сделать, и какие последствия будут вызваны тем, что не делают это, поэтому я напишу эту статью, чтобы объяснить ее.
Прежде всего, что произойдет, если мы напрямую используем следующий класс человека в качестве ключа и храним его в Hashmap?
Public Class Person {Private String ID; Public Person (String Id) {this.id = id; }} import java.util.hashmap; открытый класс main {public static void main (string [] args) {hashmap <человек, строка> map = new hashmap <person, string> (); map.put (новый человек ("001"), "superseaea"); map.put (новый человек ("002"), "linyin"); map.put (новый человек ("003"), "henrylin"); map.put (новый человек ("003"), "Rendingsealy"); System.out.println (map.toString ()); System.out.println (map.get (новый человек ("001"))); System.out.println (map.get (новый человек ("002"))); System.out.println (map.get (новый человек ("003"))); }}Так каков результат выходного вывода?
{Person@6e4d4d5e = henrylin, человек@275cea3 = fundingsea, человек@15128ee5 = fundingsealy, человек@4513098 = linyin} nullnullnullМы видим, что здесь есть две проблемы:
1. В процессе добавления мы добавляли пара значений ключа = новый человек ("003") дважды. В ожиданиях в HashMap должна быть только одна такая пара ключевых значений. Поскольку ключ (ожидаемый) такой же, его не следует добавлять неоднократно. Value = "findingsealy" добавлено, что второй раз должен заменить исходное значение = "henrylin". Но при вводе мы обнаружили, что ожидаемой ситуации не произошла, но в Hashmap есть две пары ключевых значений = "вывода" и value = "henrylin", и их ключевые значения все еще различны, что, очевидно, неверно.
2. При получении значения значения мы используем три человека объекты для поиска. Эти три объекта такие же, как и три значения ключа, которые мы только что хранили (в ожидании), но поиск - три нулевых значения, что, очевидно, также неправильно.
Таким образом, правильный метод фактически был описан во многих местах. Класс человека напрямую изменен, перегружена равенства и методы хэшкода, а класс модифицированного человека выглядит следующим образом:
Public Class Person {Private String ID; Public Person (String Id) {this.id = id; } @Override public boolean equals (object o) {if (this == o) вернуть true; if (o == null || getClass ()! = o.getClass ()) вернуть false; Личность = (человек) o; if (id! = null?! id.equals (person.id): person.id! = null) вернуть false; вернуть истину; } @Override public int hashcode () {return id! = Null? id.hashcode (): 0; }}Затем, когда мы переоцениваем вышеуказанную процедуру проверки, результаты следующие:
{Person@ba31 = fundingsea, person@ba32 = linyin, человек@ba33 = foundingsealy} foundingsealinyinfindingsealyКак видно, все отмеченные основные моменты и ошибки были исправлены. Итак, почему это происходит?
В HashMap порядок сравнения поисковых ключей состоит в том, чтобы:
1. Рассчитайте хэш -код объекта, чтобы увидеть, существует ли он в таблице.
2. Проверьте, равно ли объект в соответствующем расположении кода хэша равным текущему объекту.
Очевидно, что первым шагом является использование метода HashCode (), а второй шаг - использовать метод equals (). Когда перегрузка не выполняется, эти два метода класса объекта будут вызваны по умолчанию в этих двух шагах. В объекте метод расчета хеш -кода рассчитывается на основе адреса объекта. Адреса объекта двух человек («003») разные, поэтому их хэш -код также отличается. Естественно, HashMap не будет относиться к ним как к тому же ключу. В то же время, по умолчанию Equals () объекта, он также сравнивается на основе адреса объекта. Естественно, один человек («003») и другой человек («003») не равны.
Понимая это, легко выяснить, почему вам нужно перегружать как HashCode (), так и равенство методам.
• Перегрузка HashCode () - это получение того же хеш -кода для того же ключа, чтобы HashMap мог быть расположен на указанном нами ключе.
• Перегрузка equals () состоит в том, чтобы показать HashMap, что текущий объект и объект, сохраненный на клавише, равны, так что мы можем по-настоящему получить пару клавиш, соответствующую ключу.
Есть еще одна деталь. В классе человека акцент на методе HashCode ():
@OverridePublic int hashcode () {return id! = Null? id.hashcode (): 0;}Смысл, который можно озадачить здесь: почему хэш -код переменной строки типа может использоваться в качестве значения хэш -кода класса человека? Равенства ли хэш -коды нового человека (новая строка ("003")) и нового человека (новая строка ("003")))?
Давайте посмотрим на вывод следующего кода:
System.out.println ("findingsea" .hashcode ()); System.out.println ("findingsea" .hashcode ()); System.out.println (new String ("findingsea"). Hashcode ()); System.out.println (новый String ("findingsea"). Hashcode ()); 728795174728795174728795174728795174Вы можете видеть, что выходы четырех операторов равны. Очень интуитивно понятно и разумно предположить, что тип строки также перегружает hashcode (), чтобы вернуть значение хэш -кода в соответствии с содержанием строки, поэтому строки с тем же контентом имеют тот же хэш -код.
В то же время это также иллюстрирует вопрос: зачем нам использовать equals () для сравнения, когда мы знаем, что hashcode () равна? Это связано с тем, что он избегает ситуации в приведенном выше примере, поскольку в соответствии с реализацией перегрузки метода HashCode () класса человека, класс Person напрямую будет использовать значение хэш -кода идентификатора члена типа строки в качестве значения его хэш -кода. Тем не менее, очевидно, что человек («003») и строка («003») не равны, поэтому, когда для сравнения также необходимо сравнить HashCode (), также необходимо.
Следующие примеры могут быть использованы в качестве доказательства приведенного выше описания:
System.out.println (новый человек ("003"). Hashcode ()); // 47667system.out.println (new String ("003"). HashCode ()); // 47667system.out.println (новый человек ("003"). Equals (new String ("003"))); // ЛОЖЬПриведенная выше статья Java использует индивидуальные классы в качестве примера значения ключа HashMap. Это весь контент, которым я делюсь с вами. Я надеюсь, что это может дать вам ссылку, и я надеюсь, что вы сможете поддержать Wulin.com больше.