powered by simpleCommunicator - 2.0.61     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / Java [игнор отключен] [закрыт для гостей] / переопределние hash code
32 сообщений из 32, показаны все 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
переопределние hash code
    #39498846
Фотография Blazkowicz
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
arrtТо есть будут постоянные колизии и что? Хешмап будет неправильно работать или система будет очень долго разрешать эти колизии?
Производительность выборки из HashMap будет хуже чем полный перебор по массиву. Вся польза от структуры HashMap нивелируется.

arrtЕсли все таки в большинстве случаев есть зависимость иквала от хешмап почему не будет возвращать truе - как тогда система будет "бороться" с этой несправедливостью и какой механизм вместо сравнение хешкодов приведет к решению проблемы колизий.

Какой-то набор слов. Какая ещё несправедливость? Кто должен true возвращать?

arrtВот действительно раньше думал что иквал() сравнивает типы обьектов, потом их все поля, а функция хешкод -- есть лиш быстрой альтернативой более громзкого первого метода.
Assumption is the mother of all fuck ups. Не нужно выдумывать то что написано в документации.

arrtИ я читал джава документацию - там о какой то ссылке на адрес обьекта в памяти речь идет -- а задали мне вопрос на засыпку и делай что хочеш если этот "адрес" будет 1?
Вы путаете причину и следствие. То что java.lang.Object.hashCode() реализован определенным образом совершенно не значит что вашим объектам подойдёт такая реализация.

arrtХотя снова таки функция на практике как и написано в документации нужна в хешмапе и хешсете.
HashSet это обертка над HashMap.

arrtА какая дефолтная реализация двух методов для класа Objеct так не понял.
Код: java
1.
2.
3.
 public boolean  equals(Object obj) {
        return (this == obj);
 }
...
Рейтинг: 0 / 0
переопределние hash code
    #39498849
Alexey Tomin
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
marcomanarrtА какая дефолтная реализация двух методов для класа Objеct так не понял
/java/jdk/1.8.0.121_64/src.zip/java/lang/Object.java

Ну увидешь ты там native, и что? Там 5, что ли, реализаций, можно выбирать ключиком при старте.
В актуальной версии по-умолчанию некоторая функция от состояния потока в момент создания объекта. Это недавно случайно включили (и даже известно, кто включил, народ прикалывался на эту тему)

arrtТо есть будут постоянные колизии и что? Хешмап будет неправильно работать или система будет очень долго разрешать эти колизии?

Если объект Comparable, то будет построено дерево. И поиск объекта будет идти худо-бедно не очень медлено.
Если нет (или в старых версиях jdk-всегда)- то тупо список и сравнивать equals при каждого. Как результат- была атака на java-сервера через кучи запросов с совпадающим hash (для String подобрать такие просто).
...
Рейтинг: 0 / 0
переопределние hash code
    #39499336
arrt
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Дефолтную реализацию иквала() привели, а хешкода нет. Хотя если сравниваются ссылки то это тот же заувулированый хешкод с адресом. А мое представление о сравнение типа и полей вообще ни к чему не годится ибо однаковых обьектов можно создать сколь угодно. Но как тогда реализировать эти методы к хешсету, вот здесь именно не надо дубликатов. Аналогично к хешмапу - с включением хешкода в иквал? Или мой подход как раз подойдет ибо если обьекты одного типа имеют те же поля значит это дубликат - и снова добавлять в колекцию нельзя?
...
Рейтинг: 0 / 0
переопределние hash code
    #39499593
marcoman
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Alexey TominНу увидешь ты там native, и что?javadoc метода.
...
Рейтинг: 0 / 0
переопределние hash code
    #39499601
Фотография Blazkowicz
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
arrtДефолтную реализацию иквала() привели, а хешкода нет.
Она зависит от настроект и реализации JVM. Я могу найти его в исходниках OpenJDK. Но она вам вообще никак не поможет. Вам бы понимания.

arrtХотя если сравниваются ссылки то это тот же заувулированый хешкод с адресом.
Ну, как бы, да.

arrtА мое представление о сравнение типа и полей вообще ни к чему не годится ибо однаковых обьектов можно создать сколь угодно.

Сложно комментировать. Что у вас за представление - не знаю.

arrt Но как тогда реализировать эти методы к хешсету, вот здесь именно не надо дубликатов.
Кому реализаовать? Вам? Есть куча статей по этому поводу. Есть генераторы в IDE и есть библотеки, которые помогают автоматизировать реализацию этих методов.

arrt
Аналогично к хешмапу - с включением хешкода в иквал?

Вы кажется пропустили мой предыдущий коментарий если до сих пор их разделяете.
http://grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/6-b14/java/util/HashSet.java

arrt Или мой подход как раз подойдет ибо если обьекты одного типа имеют те же поля значит это дубликат - и снова добавлять в колекцию нельзя?
Вы немного путаетесь в терминологии.
1. Поля о объектов одного типа - одни и те же. Так как поля определяются классом, то есть типом. Вы хотели написать "значение полей", но не написали.
2. Да, зачастую, вычисление hashCode и equals() основано на полях класса. Но нужно аккуратно выбирать на каких именно полях класса. Потому что для mutable объектов, изменение значение поля может привести к изменению значения hashCode, что фатально для HashMap. Поэтому если у вас все поля объекта изменяемые, то, возможно, есть смысл оставить дефолтную реализацию.
...
Рейтинг: 0 / 0
переопределние hash code
    #39501500
arrt
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Blazkowicz, А как ситуация состоит в .nеt касательно методов (get)hashcode(), equals()?
...
Рейтинг: 0 / 0
переопределние hash code
    #39501513
Фотография Blazkowicz
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
arrtBlazkowicz, А как ситуация состоит в .nеt касательно методов (get)hashcode(), equals()?
https://msdn.microsoft.com/en-us/library/system.object(v=vs.110).aspx
...
Рейтинг: 0 / 0
32 сообщений из 32, показаны все 2 страниц
Форумы / Java [игнор отключен] [закрыт для гостей] / переопределние hash code
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


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