Мы все знаем, что язык Java полностью ориентирован на объект. В Java все объекты унаследованы от класса объектов.
Метод Equals сравнивает адреса, указанные по ссылкам двух объектов. HashCode - это локальный метод, который возвращает значение адреса объекта. В классе ojbect есть два метода. Эти два метода используются для сравнения, равны ли два объекта.
Почему мы должны переопределить метод хэшкода, переписывая метод равных?
Это можно понять следующим образом: после переписывания метода равных, бизнес -логика для оценки равенства объектов изменится. Дизайнер класса не хочет сравнивать равенство двух объектов, сравнивая адрес памяти. Бессмысленно продолжать сравнивать в соответствии с адресом. Итак, это просто изменилось вместе.
Другая причина исходит из коллекций. Давайте поговорим об этом медленно внизу ~
Например:
В школе именно через учащийся идентификатор определить, принадлежит ли этот человек.
Сценарий в приведенном ниже коде - это запись студента, номер 123 студента, назначен студенту Тому, студенту 456, назначен студенту Джерри, а студент номер 123 назначен лилию по ошибке. Однако тот же номер студента не должен происходить в процессе зачисления статуса студента.
В зависимости от ситуационных требований, дублирующие объекты не могут быть добавлены и могут быть реализованы через хэшсет.
Общедоступный класс {public static void main (string [] args) {студент stu = new Student (123, "tom"); hashset <toold> set = new hashset <> (); set.add (stu); set.add (новый студент (456, "jerry")); set.add (new Student (123, "Lily"); while (iterator.hasnext ()) {студент студента = итератор.next (); System.out.println (student.getStunum () + "---" + student.getName ());}}}; класс Студент {private int stunum; private String name; public Student (int Stunum, String name) {this.stunum = stunum; this.name = name;} public getStunum () {return stunum; name;}@overridepublic boolean equals (Object obj) {if (this == obj) вернуть true; if (obj exancefulf attuly) {if (this.getStunum () == ((студент) obj) .getStunum ()) вернуть true;} вернуть false;}}}}}}}}}}}}}}}}}}}} Вывод:
123 --- Лили
456 --- Джерри
123 --- Том
Основываясь на выходе, мы обнаружили, что назначение числа студентов 123 к Лили снова преуспело. Что пошло не так?
Давайте посмотрим на метод добавления хешса:
public boolean add (e e) {return map.put (e, present) == null;} На самом деле, Hashset реализуется через HashMap, поэтому мы отследим метод PUT Hashmap:
public v put (k key, v value) {if (table == umpty_table) {inflateatable (threshold);} if (key == null) return putfornullkey (value); int hash = hash (key); int i = indexfor (hash, table.length); для (intry <k, v> e = table [i]; == hash && ((k = e.key) == key || key.equals (k))) {v oldvalue = e.value; e.value = value; e.recordaccess (this); return oldvalue;}} modcount ++; addentry (hash, ключ, значение, i); netural null;} modcount ++;1. Согласно ключу, то есть объект, который будет добавлен Hashset, получите хэшкод, а HashCode используется для выполнения определенных операций битов для получения хэш -кода;
2. Используйте позиционирование хеш -кода, чтобы найти подписание массива, чтобы получить заголовок ссылки связанного списка;
3. Переверните связанный список, чтобы узнать, есть ли тот же ключ. Основой для суждения является e.hash == hash && ((k = e.key) == key || key.equals (k)). При добавлении лилии, поскольку метод равных переписан, второе условие должно быть правдой при переселении Тома; Но поскольку метод хэшкода по -прежнему использует родительский класс, хэшкод Тома и Лили отличается, то есть хэш -код отличается, а первое условие является ложным. Здесь мы понимаем, что два объекта разные, поэтому Hashset успешно добавляет Лили.
Причина в том, что метод хэшкода не переписывается. Вот модификация:
Общедоступный класс {public static void main (string [] args) {студент stu = new Student (123, "tom"); hashset <toold> set = new hashset <> (); set.add (stu); set.add (новый студент (456, "jerry")); set.add (new Student (123, "Lily"); while (iterator.hasnext ()) {студент студента = итератор.next (); System.out.println (student.getStunum () + "---" + student.getName ());}}}; класс Студент {private int stunum; private String name; public Student (int Stunum, String name) {this.stunum = stunum; this.name = name;} public getStunum () {return stunum; name;}@overridepublic boolean equals (Object obj) {if (this == obj) вернуть true; if (obj exancef student) {if (this.getStunum () == ((студент) obj) .getStunum ()) вернуть true;} вернуть false;}@overpublic int hashcode () {return getStun ();}@overpublic int hashcode () {return getStun ();); Выход:
456 --- Джерри
123 --- Том
Перепишите метод хэшкода и верните номер студента. Хорошо, это сделано.
Некоторые люди могут задаться вопросом, e.hash == hash && ((k = e.key) == key || key.equals (k)) немного сложно? Я думаю, что этого достаточно, чтобы просто использовать метод Equals. Зачем вам судить о хешкоде за один раз?
Поскольку при переселении и оценке в связанной структуре списка HashMap бизнес -логика переписываемых равных, более сложна для сравнения, равны ли объекты в определенных ситуациях, а бизнес -логика зацикливания повлияет на эффективность поиска. Итак, здесь мы сначала поместили суждение о хешкоде. Пока хешкод не равен, вы закончите игру, и больше нет необходимости вызывать комплекс равным. Повышение эффективности HashMap в значительной степени.
Следовательно, метод хэшкода состоит в том, чтобы позволить нам использовать классы сбора, такие как HashMap обычно, потому что HashMap определяет, являются ли объекты равными, как HashCode, так и сравнение равно. Эта реализация заключается в повышении эффективности HashMap.