powered by simpleCommunicator - 2.0.61     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / Java [игнор отключен] [закрыт для гостей] / переопределние hash code
25 сообщений из 32, страница 1 из 2
переопределние hash code
    #35741720
idb
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Всем привет! Народ объясните плиз зачем переопределять hashCode() при переопределении equals()? Если сравнение объектов происходит через метод equals().

Заранее всем спасибо!
...
Рейтинг: 0 / 0
переопределние hash code
    #35741824
GavrilovD
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
idbВсем привет! Народ объясните плиз зачем переопределять hashCode() при переопределении equals()? Если сравнение объектов происходит через метод equals().

Заранее всем спасибо!
Потому что согласно документации, метод hashCode у одинаовых объектов должен быть одинаковым. Обычно, по умолчанию класс Object, от которого наследуются все классы в Java, в методе hashCode - возвращает адрес объекта в памяти (This is typically implemented by converting the internal address of the object into an integer, but this implementation technique is not required by the JavaTM programming language.)...

В идеале, должны получить нечто следующее (только лишь пример, не более)
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
 public   class  Customer  implements  Serializable {
	 private   static   final   long  serialVersionUID = -403805696281063111L;

	 private   long  id;
	
	 public   long  getId() {
		 return  id;
	}
	
	 protected   void  setId( long  id) {
		 this .id = id;
	}
	
	@Override
	 public   int  hashCode() {
		 return  ( int )id;
	}
	
	@Override
	 public   boolean  equals(Object object) {
		 if (object ==  null  || !(object  instanceof  Customer) ) {
			 return  false;			
		}
		Customer other = (Customer)object;
		 return  other.hashCode() ==  this .hashCode();
	}
}
...
Рейтинг: 0 / 0
переопределние hash code
    #35741948
Leshij
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Потому что иначе объекты будут неправильно храниться в контейнерах,
основанных на хэшах (HashMap, HashSet).
Posted via ActualForum NNTP Server 1.4
...
Рейтинг: 0 / 0
переопределние hash code
    #35742166
Vurn
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
GavrilovD
В идеале, должны получить нечто следующее (только лишь пример, не более)
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
 public   class  Customer  implements  Serializable {
//...	
	@Override
	 public   int  hashCode() {
		 return  ( int )id;
	}
//...
}


hashCode() от лонга обычно делается так:
Код: plaintext
1.
2.
3.
4.
5.
6.
	@Override
	 public   int  hashCode() {
		 return  ( int )((id>>> 32 ) ^ id);
	}
//...
}

Таким образом получается равновесный hashCode, который правильно реагирует на изменение старших 32 битов long'a
...
Рейтинг: 0 / 0
переопределние hash code
    #35742466
GavrilovD
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
VurnGavrilovD
В идеале, должны получить нечто следующее (только лишь пример, не более)
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
 public   class  Customer  implements  Serializable {
//...	
	@Override
	 public   int  hashCode() {
		 return  ( int )id;
	}
//...
}


hashCode() от лонга обычно делается так:
Код: plaintext
1.
2.
3.
4.
5.
6.
	@Override
	 public   int  hashCode() {
		 return  ( int )((id>>> 32 ) ^ id);
	}
//...
}

Таким образом получается равновесный hashCode, который правильно реагирует на изменение старших 32 битов long'a
Да, как вариант... согласен. Но это уже вопрос формирования самого hashCode, а не почему его надо переопределять при переопределении метода equals
...
Рейтинг: 0 / 0
переопределние hash code
    #35742532
xifr
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Вопрос в тему, всегда было интересно, как правильнее делать?

Если hashCode расчитывается на основание нескольких переменных и получается не тривиальный расчёт
я так понимаю при своей работе всякие HashMap и HashSet делают вызовы метода hashCode очень много раз, тогда получается, что тот не тривиальный расчёт будет выполнятся каждый раз, и будет занимать кучу ресурсов?
...
Рейтинг: 0 / 0
переопределние hash code
    #35742541
Фотография mayton
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
GavrilovD
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
 public   class  Customer  implements  Serializable {
	 private   static   final   long  serialVersionUID = -403805696281063111L;

	 private   long  id;
	
	 public   long  getId() {
		 return  id;
	}
	
	 protected   void  setId( long  id) {
		 this .id = id;
	}
	
	@Override
	 public   int  hashCode() {
		 return  ( int )id;
	}
	
	@Override
	 public   boolean  equals(Object object) {
		 if (object ==  null  || !(object  instanceof  Customer) ) {
			 return  false;			
		}
		Customer other = (Customer)object;
		 return  other.hashCode() ==  this .hashCode();
	}
}


Это очень плохой пример. Я могу смоделировать условия при которых разные объекты вдруг станут equal по отношению друг к другу. Придумайте пример получше.
...
Рейтинг: 0 / 0
переопределние hash code
    #35743307
Самоловских Виталий aka Kefir
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
xifrЕсли hashCode расчитывается на основание нескольких переменных и получается не тривиальный расчёт
я так понимаю при своей работе всякие HashMap и HashSet делают вызовы метода hashCode очень много раз, тогда получается, что тот не тривиальный расчёт будет выполнятся каждый раз, и будет занимать кучу ресурсов?
Во-первых, вызывается он не много раз.

Идем дальше, тяжелый расчет придумывать не надо. Теоретически константа - корректная функция для расчета хэш-кода. Но лучше все-таки рассчитывать его по нескольким полям, лучше из примитивных типов. Здесь вообще можно исходить из каких-нибудь эмпирических соображений: типа, вот эти поля у разных объектов с большой вероятностью отличаются их и включим в хэш-функцию. Но надо помнить что все поля задействованные в хэш-функции должны быть так же и задействованы при переопределении equals, иначе равные объекты смогут заиметь разные хэш-функции.

Ну и наконец, есть замечательнейшая вещь, называется кэширование. Т.е. если хэш рассчитывается сложно и долго то его надо рассчитать 1 раз и сохранить где-нить в объекте.
...
Рейтинг: 0 / 0
переопределние hash code
    #35743355
Фотография mayton
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Функция хеширования как правило вычисляется достаточно быстро. Это одно из требований которое было предъявлено к ней создателями. В большинстве случаев, хеширование - это композиция операций взятия остатка от деления, умножения на некое иррациональное число (напр. золотое сечение) и округление. Для стринговых аргументов метод может быть немного сложнее но суть остаётся та-же.

Поэтому, думаю, кеширование здесь будет ненужным.
...
Рейтинг: 0 / 0
переопределние hash code
    #35744758
забыл ник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ИМХО если есть возможность сделать объект immutable, то сделать его таким и потом действительно пройтись по всем полям и сохранить где-нибудь в поле класса вычисленное значение, но это для паранойиков
...
Рейтинг: 0 / 0
переопределние hash code
    #35745151
Фотография mayton
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Точно. Для параноиков.
...
Рейтинг: 0 / 0
переопределние hash code
    #35771100
idb
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
То есть правильно ли я понял, что переопределение hashcode необходимо из-за:
объекты в первую очередь сравниваются (метод equals) по hashcode, который в свою очередь быстро вычисляется, соответственно метод equals намного быстрее отрабатывает?
...
Рейтинг: 0 / 0
переопределние hash code
    #35771273
vas0
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
idbТо есть правильно ли я понял, что переопределение hashcode необходимо из-за:
объекты в первую очередь сравниваются (метод equals) по hashcode, который в свою очередь быстро вычисляется, соответственно метод equals намного быстрее отрабатывает?
Нет не правильно. Как работают хэш таблицы, чтобы быстро отвечать на вопрос содержится ли добавляемое значение в таблице или нет?

Сначала по hashCode находят требуюмую "ячейку". В этой "ячейке" может быть несколько значений, среди этих значений сравнение уже идет используя метод equals.

ЗЫ по терминологии я тут наврал, но общий смысл такой.
...
Рейтинг: 0 / 0
переопределние hash code
    #35849450
2ak
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
я вот тоже недопонимал, смысл переопредления hashCode.

Правильно ли я понял из объясений?
Есть у меня экземпляры классов Car и Driver, соответственно Car1, Car2 и Driver1, Driver2. Судя по вышеприведенным объяснениям Car1 и Car2 будут лежать в одной ячейке и например с ключем hashCode=123, а Driver1 и Driver2 будут лежать в другой ячейке и например с ключем hashCode=124.
...
Рейтинг: 0 / 0
переопределние hash code
    #35849461
Фотография mayton
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Правильно. Еще вариант - (Car1,Driver1), (Car2,Driver2). Главное, чтобы все ячейки хранили примерно одинаковое количество значений с ростом объема хеш-таблицы. В этом случае функция будет "добротной" и количество промахов поиска будет минимальным.
...
Рейтинг: 0 / 0
переопределние hash code
    #35849468
2ak
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
а тогда по какому принципу они распределяются по ячейкам?
...
Рейтинг: 0 / 0
переопределние hash code
    #35849478
Фотография Frenzy
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
xifrВопрос в тему, всегда было интересно, как правильнее делать?

Если hashCode расчитывается на основание нескольких переменных и получается не тривиальный расчёт
я так понимаю при своей работе всякие HashMap и HashSet делают вызовы метода hashCode очень много раз, тогда получается, что тот не тривиальный расчёт будет выполнятся каждый раз, и будет занимать кучу ресурсов?

почитайте Блоха "Effective Java" 2nd ed.
...
Рейтинг: 0 / 0
переопределние hash code
    #35849480
2ak
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
maytonПравильно. Еще вариант - (Car1,Driver1), (Car2,Driver2). Главное, чтобы все ячейки хранили примерно одинаковое количество значений с ростом объема хеш-таблицы. В этом случае функция будет "добротной" и количество промахов поиска будет минимальным.

Наверно, такой вариант вероятнее всего если Car1.getId() =1 и Driver1.getId() =1, Car2.getId() =2 и Driver2.getId() =2 и при условии что у Сar и Driver :
Код: plaintext
1.
2.
3.
4.
 public   int  hashCode() {
 int  result = hashCode;        
 return  result =  31  * result + getId();
 }
...
Рейтинг: 0 / 0
переопределние hash code
    #35849488
Фотография mayton
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Я изучал работу хеша, но не в Java а в других С-подобных библиотеках. Поэтому могу ошибатся в деталях. Но в общем это выглядит как-то так. Изначально вы создаёте хеш с двумя параметрами. Initial_capacity и load_factor . Первый показывает, сколько элементов будет хранить хеш в стационарном состоянии, второй - коэффициент загрузки. Изначально он равен 0.75. Это что-то вроде на 100 элементов приходится 75 ячеек. Величину можно уменьшить но не увеличить. Теоретики утверждают что при таком соотношении хеш работает эффективно. При деградации количества элементов его скоростные характеристики улучшаются. Промахи практически полностью уходят. С ростом количества элементов - ситуация более сложная. Пропорция 0.75 нарушается, поисковые операции замедляются и хеш необходимо реорганизовать. Как это происходит в Java я точно не знаю но в .Net аналогичный контейнер выполняет создание нового хеша с объемом в два раза больше и реплицирует элементы старого хеша в новый. Старый после этого удаляется. По производительности - это тяжёлая операция. Её даже можно видеть ощутимо в task-manager при количестве элементов порядка несколько млн. Поэтому желательно создавать хеш заранее известного объёма чтобы избежать таких встрясок.

Дополнительно можешь посмотреть документацию по классу HashMap. Обрати внимание на его конструкторы.
...
Рейтинг: 0 / 0
Период между сообщениями больше года.
переопределние hash code
    #39497385
arrt
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Когда-то перед до мной был такой вопрос - что будет если в обьектов функция hashcode() будет возвращать одинаковое значение, например 1? С прочитаного здесь я понял что все обьекты, например в hаshmаp, будут возвращать в методе еquаls() truе и будут считатся одинаковыми? Раньше думал что в эквале нету зависимости от хешкод, в этой теме она представлена. Это обязательная зависимость?
...
Рейтинг: 0 / 0
переопределние hash code
    #39497505
Фотография Hett
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
arrt,

прочитай внимательно все что написали в этой теме, объекты с одинаковым хеш кодом не обязательно "равны".
...
Рейтинг: 0 / 0
переопределние hash code
    #39497552
Фотография Blazkowicz
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
arrtКогда-то перед до мной был такой вопрос - что будет если в обьектов функция hashcode() будет возвращать одинаковое значение, например 1?
HashMap из таких объектов будет работать крайне не эффективно, из-за постоянных коллизий.

arrtС прочитаного здесь я понял что все обьекты, например в hаshmаp, будут возвращать в методе еquаls() truе и будут считатся одинаковыми?
Не будет equals() возвращать true. Прочитайте внимательно не только эту ветку, но и JavaDoc класса java.lang.Object.

arrtРаньше думал что в эквале нету зависимости от хешкод, в этой теме она представлена.
Зависимость есть. Но она совсем не такая как вы решили.

arrtЭто обязательная зависимость?
Как бы, обязательная по документации. Но к очевидным ошибкам в runtime или compile-time отсутсвие этой зависимости не приводит.
...
Рейтинг: 0 / 0
переопределние hash code
    #39498666
arrt
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
То есть будут постоянные колизии и что? Хешмап будет неправильно работать или система будет очень долго разрешать эти колизии? Если все таки в большинстве случаев есть зависимость иквала от хешмап почему не будет возвращать truе - как тогда система будет "бороться" с этой несправедливостью и какой механизм вместо сравнение хешкодов приведет к решению проблемы колизий. Вот действительно раньше думал что иквал() сравнивает типы обьектов, потом их все поля, а функция хешкод -- есть лиш быстрой альтернативой более громзкого первого метода. И я читал джава документацию - там о какой то ссылке на адрес обьекта в памяти речь идет -- а задали мне вопрос на засыпку и делай что хочеш если этот "адрес" будет 1? Хотя снова таки функция на практике как и написано в документации нужна в хешмапе и хешсете. А какая дефолтная реализация двух методов для класа Objеct так не понял.
...
Рейтинг: 0 / 0
переопределние hash code
    #39498834
marcoman
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
arrtА какая дефолтная реализация двух методов для класа Objеct так не понял
/java/jdk/1.8.0.121_64/src.zip/java/lang/Object.java
...
Рейтинг: 0 / 0
переопределние hash code
    #39498835
marcoman
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
arrtВот действительно раньше думал что иквал() сравнивает типы обьектов, потом их все поля, а функция хешкод -- есть лиш быстрой альтернативой более громзкого первого метода.Как реализуешь, так и будет "сравнивать".
arrtХешмап будет неправильно работать или система будет очень долго разрешать эти колизии? https://habrahabr.ru/post/128017/
...
Рейтинг: 0 / 0
25 сообщений из 32, страница 1 из 2
Форумы / Java [игнор отключен] [закрыт для гостей] / переопределние hash code
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]