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

Заранее всем спасибо!
...
Рейтинг: 0 / 0
30.12.2008, 16:18
    #35741824
GavrilovD
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
переопределние hash code
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
30.12.2008, 17:20
    #35741948
Leshij
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
переопределние hash code
Потому что иначе объекты будут неправильно храниться в контейнерах,
основанных на хэшах (HashMap, HashSet).
Posted via ActualForum NNTP Server 1.4
...
Рейтинг: 0 / 0
30.12.2008, 21:36
    #35742166
Vurn
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
переопределние hash code
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
31.12.2008, 10:33
    #35742466
GavrilovD
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
переопределние hash code
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
31.12.2008, 11:34
    #35742532
xifr
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
переопределние hash code
Вопрос в тему, всегда было интересно, как правильнее делать?

Если hashCode расчитывается на основание нескольких переменных и получается не тривиальный расчёт
я так понимаю при своей работе всякие HashMap и HashSet делают вызовы метода hashCode очень много раз, тогда получается, что тот не тривиальный расчёт будет выполнятся каждый раз, и будет занимать кучу ресурсов?
...
Рейтинг: 0 / 0
31.12.2008, 11:41
    #35742541
mayton
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
переопределние hash code
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
02.01.2009, 18:14
    #35743307
Самоловских Виталий aka Kefir
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
переопределние hash code
xifrЕсли hashCode расчитывается на основание нескольких переменных и получается не тривиальный расчёт
я так понимаю при своей работе всякие HashMap и HashSet делают вызовы метода hashCode очень много раз, тогда получается, что тот не тривиальный расчёт будет выполнятся каждый раз, и будет занимать кучу ресурсов?
Во-первых, вызывается он не много раз.

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

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

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

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

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

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

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

почитайте Блоха "Effective Java" 2nd ed.
...
Рейтинг: 0 / 0
03.03.2009, 22:13
    #35849480
2ak
2ak
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
переопределние hash code
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
03.03.2009, 22:22
    #35849488
mayton
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
переопределние hash code
Я изучал работу хеша, но не в Java а в других С-подобных библиотеках. Поэтому могу ошибатся в деталях. Но в общем это выглядит как-то так. Изначально вы создаёте хеш с двумя параметрами. Initial_capacity и load_factor . Первый показывает, сколько элементов будет хранить хеш в стационарном состоянии, второй - коэффициент загрузки. Изначально он равен 0.75. Это что-то вроде на 100 элементов приходится 75 ячеек. Величину можно уменьшить но не увеличить. Теоретики утверждают что при таком соотношении хеш работает эффективно. При деградации количества элементов его скоростные характеристики улучшаются. Промахи практически полностью уходят. С ростом количества элементов - ситуация более сложная. Пропорция 0.75 нарушается, поисковые операции замедляются и хеш необходимо реорганизовать. Как это происходит в Java я точно не знаю но в .Net аналогичный контейнер выполняет создание нового хеша с объемом в два раза больше и реплицирует элементы старого хеша в новый. Старый после этого удаляется. По производительности - это тяжёлая операция. Её даже можно видеть ощутимо в task-manager при количестве элементов порядка несколько млн. Поэтому желательно создавать хеш заранее известного объёма чтобы избежать таких встрясок.

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

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

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

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

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


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