Модераторы: LSD, AntonSaburov

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Основы. Object.hashCode(), расскажите смысл и правила пож. 
:(
    Опции темы
Sleepy_PIP
Дата 13.5.2005, 10:48 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 512
Регистрация: 30.6.2004
Где: Moscow

Репутация: 4
Всего: 12



Вот, решил что хватит по верхушкам бродить. Не стыжусь спросить.
Копнул, и выяснилось что я до конца не понимаю смысла хеш-кода у Object и правила его формирования.
Хелп:
The general contract of hashCode is:

-Whenever it is invoked on the same object more than once during an execution of a Java application, the hashCode method must consistently return the same integer, provided no information used in equals comparisons on the object is modified. This integer need not remain consistent from one execution of an application to another execution of the same application.

т.е. если я создаю экземпляры некоего класса как и все, расширяющего Object - то у 2-х моих экземпляров хеш-код может быть одинаков?


-If two objects are equal according to the equals(Object) method, then calling the hashCode method on each of the two objects must produce the same integer result.

т.е. 2 одинаковых объекта имеют один хеш-код. тут понятно. но не до конца понятно - что есть 2 именно одинаковых объекта.

т.е.
TTst a,b;
a=new TTst;
b=new TTst;
a.equals(b) - true или false?

а после
a.prop1=1;
b.prop1=2;
a.equals(b) - true или false?

т.к. про equals написано:
==========
The equals() method compares two objects of the same type for equality

by comparing the properties of both objects.
^^^^^^^^^^^^^^^^^^^^^^^^^^^^

It simply returns a boolean value depending on the results of the object that calls it and the object that is passed to it. For instance, if equals() is called by an object that passes it an object that is identical, the equals() method returns a true value
=============

-It is not required that if two objects are unequal according to the equals(java.lang.Object) method, then calling the hashCode method on each of the two objects must produce distinct integer results. However, the programmer should be aware that producing distinct integer results for unequal objects may improve the performance of hashtables

тут говорят что если a.euals(b)==false - то хешкод у a и b - разный. так?

что-то я запутался.
поставте обратно меня на рельсы, а?
Спасибо!



--------------------
--
Sleepy_PIP. Pavel Pryazhentsev (ex. 2:5020/141) "... Лучше быть нужным, чем
свободным ..."
PM MAIL ICQ   Вверх
Domestic Cat
Дата 13.5.2005, 11:05 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Экс. модератор
Сообщений: 5452
Регистрация: 3.5.2004
Где: Dallas, US

Репутация: 50
Всего: 172



Цитата(Sleepy_PIP @ 13.5.2005, 01:48)
т.е. если я создаю экземпляры некоего класса как и все, расширяющего Object - то у 2-х моих экземпляров хеш-код может быть одинаков?


Да.


Цитата(Sleepy_PIP @ 13.5.2005, 01:48)
т.е. 2 одинаковых объекта имеют один хеш-код. тут понятно. но не до конца понятно - что есть 2 именно одинаковых объекта.


Это два объекта, для которых equals возвращает true.


Цитата(Sleepy_PIP @ 13.5.2005, 01:48)
тут говорят что если a.euals(b)==false - то хешкод у a и b - разный. так?


Да.

Если вкратце: equals ДОЛЖЕН ПО ИДЕЕ возвращать true если оба объекта одинаковы по свойствам. Но по умолчанию, если его не переопределить, он возвратит то же, что и ==.
А == сравнивает ссылки, и возвращает тру если обе ссылки ссылаются на один объект. equals ты можешь определять как угодно, по равенству всех полей, или некоторых полей.

Хеш код нужен для хешмапов, хештейблов, хешсетов. Он ничего не значит, просто придуман для того, чтобы хеш-коллекции были эффективными. Потому он и определен так, как ты процитировал: если два объекта равны через equals, они обязаны иметь один хешкод, но равенство хешкодов не означает равенства через equals.



--------------------

PM   Вверх
Sleepy_PIP
Дата 13.5.2005, 20:36 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 512
Регистрация: 30.6.2004
Где: Moscow

Репутация: 4
Всего: 12



Большое СПАСИБО!


--------------------
--
Sleepy_PIP. Pavel Pryazhentsev (ex. 2:5020/141) "... Лучше быть нужным, чем
свободным ..."
PM MAIL ICQ   Вверх
hatsumeika
Дата 14.5.2005, 18:28 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 51
Регистрация: 14.5.2005
Где: Минск

Репутация: 2
Всего: 2



Если hashCode не переопределить, то нельзя будет класс использовать в HashMap, HashSet и т.п. в качестве ключей. Потому что они сначала ищут по hashCode, а только потом по equals.

Не будет ничего страшного если реализовать hashCode() как return 13; Конечно в HashMap, HashSet все сведется к полному перебору.
Отсюда следствие: hashCode должен просто обеспечивать какой-то разброс значений для разных объектов, поэтому лучше использовать какое-то сравнительно уникальное поле и возвращать его hashCode
PM MAIL   Вверх
Domestic Cat
Дата 14.5.2005, 19:38 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Экс. модератор
Сообщений: 5452
Регистрация: 3.5.2004
Где: Dallas, US

Репутация: 50
Всего: 172



Цитата(hatsumeika @ 14.5.2005, 09:28)
Если hashCode не переопределить, то нельзя будет класс использовать в HashMap, HashSet и т.п. в качестве ключей. Потому что они сначала ищут по hashCode, а только потом по equals.

Неверно, использовать можно будет, а метод hashCode() будет вызываться унаследованный от Object.


--------------------

PM   Вверх
hatsumeika
Дата 14.5.2005, 21:42 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 51
Регистрация: 14.5.2005
Где: Минск

Репутация: 2
Всего: 2



формально использовать можно, только работать будет мягко говоря специфически:
вот этот код напечатает null, а не "ASD"
Код

public class NoHashCode {
  int _value;
  
  public NoHashCode(int value) {
    _value = value;
  }
  
  public static void main(String[] args) {
    HashMap<NoHashCode, String> hm = new HashMap<NoHashCode, String>();
    hm.put(new NoHashCode(21), "ASD");
    System.out.println(hm.get(new NoHashCode(21)));
  }
}

PM MAIL   Вверх
Domestic Cat
Дата 14.5.2005, 22:18 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Экс. модератор
Сообщений: 5452
Регистрация: 3.5.2004
Где: Dallas, US

Репутация: 50
Всего: 172



Цитата(hatsumeika @ 14.5.2005, 12:42)
формально использовать можно, только работать будет мягко говоря специфически:
вот этот код напечатает null, а не "ASD"


Ну тогда и equals нужен.


--------------------

PM   Вверх
hatsumeika
Дата 14.5.2005, 22:21 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 51
Регистрация: 14.5.2005
Где: Минск

Репутация: 2
Всего: 2



да, Блох рекомендует equals and hashCode переопределять вместе
PM MAIL   Вверх
Domestic Cat
Дата 14.5.2005, 22:27 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Экс. модератор
Сообщений: 5452
Регистрация: 3.5.2004
Где: Dallas, US

Репутация: 50
Всего: 172



Цитата(hatsumeika @ 14.5.2005, 13:21)
да, Блох рекомендует equals and hashCode переопределять вместе

Да нет, без него тоже будет нул давать.


--------------------

PM   Вверх
hatsumeika
Дата 14.5.2005, 22:44 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 51
Регистрация: 14.5.2005
Где: Минск

Репутация: 2
Всего: 2



согласен. надо обоих переопределять.
PM MAIL   Вверх
Sleepy_PIP
Дата 15.5.2005, 12:17 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 512
Регистрация: 30.6.2004
Где: Moscow

Репутация: 4
Всего: 12



Цитата(hatsumeika @ 14.5.2005, 18:28)
Если hashCode не переопределить, то нельзя будет класс использовать в HashMap, HashSet и т.п. в качестве ключей. Потому что они сначала ищут по hashCode, а только потом по equals.


как это, как это! - как я где-то читал (сорри, не помню где) - родной Object.hashCode пользует для построения хеш-кода в т.ч. и "адрес" объекта (ссылки) - так что довольно уникален ... а?



--------------------
--
Sleepy_PIP. Pavel Pryazhentsev (ex. 2:5020/141) "... Лучше быть нужным, чем
свободным ..."
PM MAIL ICQ   Вверх
Domestic Cat
Дата 15.5.2005, 17:53 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Экс. модератор
Сообщений: 5452
Регистрация: 3.5.2004
Где: Dallas, US

Репутация: 50
Всего: 172



Цитата(Sleepy_PIP @ 15.5.2005, 03:17)
родной Object.hashCode пользует для построения хеш-кода

Он для разных объектов даст разные значения, независимо от того, equals они или нет. Например new Integer(2) и new Integer(2) будут иметь различный хешкод.


--------------------

PM   Вверх
Sleepy_PIP
Дата 15.5.2005, 22:14 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 512
Регистрация: 30.6.2004
Где: Moscow

Репутация: 4
Всего: 12



Цитата(Domestic @ 15.5.2005, 17:53)
Цитата(Sleepy_PIP @ 15.5.2005, 03:17)
родной Object.hashCode пользует для построения хеш-кода

Он для разных объектов даст разные значения, независимо от того, equals они или нет. Например new Integer(2) и new Integer(2) будут иметь различный хешкод.

хм ... опять .. оптяь не понисмаю.
MyClass a,b;
a=new MyClass();
b=new MyClass();

что тут даст hashCode и
a.equal(b)

а теперь
a.Prop1=2;
b.Prop1=3;

что тут даст hashCode и
a.equal(b)

???
и на чем это основано?
по докам - equal - во втором случае дас false т.к. поля класса изменены ... не так?


--------------------
--
Sleepy_PIP. Pavel Pryazhentsev (ex. 2:5020/141) "... Лучше быть нужным, чем
свободным ..."
PM MAIL ICQ   Вверх
hatsumeika
Дата 16.5.2005, 18:44 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 51
Регистрация: 14.5.2005
Где: Минск

Репутация: 2
Всего: 2



если в MyClass не переопределены equals() и hashCode(), то исп. соотв. методы у Object, поэтому a.equals(b) всегда будет false.
Если переопределены, то зависит проверяется ли поле Prop1.

Короче создатель класса определяет, что такое для этого класса equals.

Например извращение: класс, объекты которого никогда ничему не равны, даже сами себе:
Код

public boolean equals(Object obj){
  return false;
}


Это сообщение отредактировал(а) hatsumeika - 16.5.2005, 18:45
PM MAIL   Вверх
AntonSaburov
Дата 16.5.2005, 19:17 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Штурман
****


Профиль
Группа: Модератор
Сообщений: 5658
Регистрация: 2.7.2002
Где: Санкт-Петербург

Репутация: 51
Всего: 118



Цитата(Domestic @ 15.5.2005, 17:53)
Например new Integer(2) и new Integer(2) будут иметь различный хешкод.

Эти будут иметь один.

"To successfully store and retrieve objects from a hashtable, the objects used as keys must implement the hashCode method and the equals method."

Вообще надо поискать информацию по хэш-функциям - для чего они. Там более подробно можно почитать. Идея в том, чтобы ускорить выборку для очень сложных объектов, которые просто сравнивать между собой очень неудобно. А хэш-функция вычисляется обычно очень быстро и для каких-то данных она уникальна для набора каких-то ключевых полей.
Например для тех же String, Integer, Double и прочая.
Если я имею класс, который хочу использовать в качестве ключа в Hashtable, то если я хочу, чтобы при равенстве какого-то набора полей я думал, что это один и тот же ключ, то я должне написать hashCode() который такое и сделает.

Если брать практический пример, то в той же Hashtable ключ используется имеено в разрезе hashCode. Т.е. если я знаю, что в моей Hastable есть ключ Integer(1) и ему соответствует "Старая строка", то операция put(Integer(1), "Новая строка") заменит строку в таблице. А не прибавит новую.
PM MAIL WWW ICQ   Вверх
Ответ в темуСоздание новой темы Создание опроса
Правила форума "Java"
LSD   AntonSaburov
powerOn   tux
javastic
  • Прежде, чем задать вопрос, прочтите это!
  • Книги по Java собираются здесь.
  • Документация и ресурсы по Java находятся здесь.
  • Используйте теги [code=java][/code] для подсветки кода. Используйтe чекбокс "транслит", если у Вас нет русских шрифтов.
  • Помечайте свой вопрос как решённый, если на него получен ответ. Ссылка "Пометить как решённый" находится над первым постом.
  • Действия модераторов можно обсудить здесь.
  • FAQ раздела лежит здесь.

Если Вам помогли, и атмосфера форума Вам понравилась, то заходите к нам чаще! С уважением, LSD, AntonSaburov, powerOn, tux, javastic.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Java: Общие вопросы | Следующая тема »


 




[ Время генерации скрипта: 0.1915 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.