написано что для каждого объекта генерируется свой хэшкод, а какой смысл сравнивать хэшкоды если они для всего разные?
hidden #2158068
25 уровень
Вопрос про метод hashCode()
Решен
Комментарии (13)
- популярные
- новые
- старые
Для того, чтобы оставить комментарий Вы должны авторизоваться
JustinianJudge в Mega City OneMaster
10 августа 2020, 13:10решение
Разные могут быть у разных классов и то не факт, а вот могут то быть и одинаковые.
А если один и тот же объект используется второй раз? Копия к примеру или даже тот же самый объект, просто две ссылки разные.
Допустим у тебя три студента, Аня, Аня (копия), Миша.
Проверка через equals занимает больше ресурсов, поэтому удобно сначала сравнить через хешкод, два инта сравнить очень быстро, поэтому быстро проверил, ага, хешкод совпадает, значит это один и тот же объект, допустим это все тот же студент Аня, просто его копия с полностью идентичными данными.
А для другого студента - Аня и Миша будут разные хэшкоды, уже мы можем быстро определить == или !=.
И если уже по хешкод совпадение тогда мы через equals сможем проверять, так работает гораздо быстрее.
По такому принципу работают коллекции, в названии которых есть слово Hash.
+2
hidden #2158068
10 августа 2020, 13:22
спасибо огромное, пол дня вникал, а хэшсэт.contains() по хэшкоду сравнивает?
0
JustinianJudge в Mega City OneMaster
10 августа 2020, 13:37
На здоровье, главное запомнить следующее - идентичность объектов сравнивается через equals.
Хеш объекта это представление объекта в некотором числе фиксированого размера.
Редко, но хеши могут быть одинаковы для разных объектов.
Поэтому идентичность мы всегда через equals сравниваем.
Хеш же используем, ммм...ну по аналогии, может имя человека.
Их много, но иногда они совпадают, и одинаковое имя Дима и Дима это еще не значит что это один и тот же человек.
Но это значительно убыстряет коммуникацию, ведь Саша, Петя, Маша, Аня, Катя, Таня, Коля, Петя сразу же отметаются, они знают - это не к ним, это к Диме.
Остаются Димы, и там уже идет конкретное (более медленное) сравнение, так какой такой Дима? Дима с такого-то города, с таким-то паспортом и налоговым номером который проживает там-то. Вот это equals, он безошибочно определить равны объекты или нет.
Но когда тебе нужно позвать друга, накладно запрашивать его паспорт, налоговый номер и проверять прописку. Быстрее крикнуть имя.
Поэтому хеш используется для построения быстрых алгоритмов сравнения, чтобы быстро сравнить (два инта сравниваются очень быстро).
Исходя из этого, хэшсэт.contains() естественно будет сравнивать и по хешкоду И по еквалс.
Я советую начинать читать исходники.
Встретил метод, нажал на название и F4 нажал (или CTRL + RIGHT MOUSE CLICK) и посмотрел что внутри.
HashSet.contains ведет нас к map.containsKey(o), нажимаем на этот метод и получаем вызов на getNode(.. );, нажимаем на getNode и видим уже код метода, где видим такое:
то есть, проверяется сначала на хеш, если они разные (мы ищем Аню, а у нас Маша, сразу промах), возвращаем false, а если хеш совпадает, ключ не налл то тогда уже проверяется объект-ключ с тем что содержится в коллекции - через equals (если ищем Аню, какая-то Аня нашлась, мы уже уточняем, какая конкретная Аня, та ли
0
hidden #2158068
11 августа 2020, 12:53
вот написал такой код, в объектах одинаковые поля. а хэшкод разный
0
JustinianJudge в Mega City OneMaster
11 августа 2020, 12:57
конечно разный, ты же нажал F4 и посмотрел реализацию метода hashCode?
У тебя в классе S не переопределен ни equals ни хешкод.
А это значит что два одинаковых, с точки зрения бизнес-логики объекта, будут неравны друг другу. То особой необходимости и для одинакового хешкода нету.
p.s. если ты быстро все схватываешь и сразу все понятно, то можешь как тебе удобно, но если ты пытаешься разобраться, а вопросы остаются - не называй шифрограммами классы. ты себе просто ставишь палку в колесо, заставляя тратить ресурсы мозга не на то, чтобы разобраться в теме, а на ментальный маппинг, вот я пишу С, это какой-то класс, а там а, это какая-то переменная, котороая обозначает то.
По закону Ломоносова, если в одном месте прибудет , в другом убудет.
Назови там Student, поля name, age, это будет гораздо наглядней
0
JustinianJudge в Mega City OneMaster
11 августа 2020, 13:03
т.е., если ты хочешь, чтобы тождество объектов сравнивалось по полям - ты должен переопределить методы equals/hashcode
Иначе будет выбрана реализация по умолчанию, для которой не существует полей, а речь идет только про идентичность фактичную сущности - это один и тот же объект в памяти или нет. Если это полная копия, но другой отдельный экземпляр класса с теми же полями, то это будет другой объект, поскольку сравниваются ссылки.
Ну и хешкод соответственно тоже будет высчитываться разный
0
hidden #2158068
12 августа 2020, 10:27
хороший совет, я так понял(и проверил) что хэшмап вызывает хэшкод и эквайлс,
они вызываются у класса который сравнивают или добавляют, в хэшмапе
0
JustinianJudge в Mega City OneMaster
12 августа 2020, 11:28
да, только вызываются не у класса, а у инстанса.
Если не читал - почитай https://habr.com/en/post/128017/ хорошая статья
0
hidden #2158068
12 августа 2020, 12:37
последний вопрос который не понимаю.
hashCode() возвращает число на основе объекта, допустим мы сравниваем по строкам в объектах. то мы переопределяя hashCode() внутри вызываем хэшкод для строки сравниваемой вот пример задачи
но разве для строк хэшкод переопределять не нужно?
и также мы можем задать свой алгоритм без вызова хэшкода для строки?
0
JustinianJudge в Mega City OneMaster
12 августа 2020, 12:50
дважды в реку входить нету необходимости.
String это класс в котором переопределены и equals , что логично, он сравнивает по содержимому объекта, а не по ссылке на экземпляр объект, и соответственно хешкод.
Опять же - нажимаешь F4 и смотришь что происходит. Ты должен постоянно это делать, чтобы понимать что происходит в твоем коде.
можем конечно, но чтобы реализовать корректную работу, тебе все-равно придется сделать приблизительно то, что содержится в переопределенном хешкоде строки, ведь ты для одинаковой последовательности символов/полей должен выдавать одинаковый хешкод, и обеспечить максимально насколько возможно, чтобы не было совпадения по хешкоду, если отличается хотя бы 1 буква с миллиона.
0
hidden #2322530
10 августа 2020, 12:57полезный
когда ты помещаешь элемент в HashMap, то вначале для каждого элемента высчитывается hashCode() и сравнивается с тем, что ты помещаешь. потому что ключи должны быть уникальными.
объекты которые хранятся в словаре, могут иметь сколько угодно внутренний полей. и как сравнить тогда 2 объекта между собой? правильно, для этого переопределяют метод hashCode(), чтобы он знал какие поля как высчитывать. на выходе получается число. если у двух объектов хэшкоды (числа) равны. значит и объекты по своей сути равны.
+1
hidden #2158068
10 августа 2020, 13:03
если объекты внутри идентичны то у них хэшкод одинаковый?
0
hidden #2322530
10 августа 2020, 13:05
да. примерно по такому принципу работает метод equals() для объектов. он высчитывает hashCode каждого, и просто сравниваются результаты между собой.
0