Когда полезен хеш-код, если я никогда не использую хеш-таблицу?

1

Допустим, я реализую класс Car, с 2 переменными-членами int numDoors и цветом String.

В гипотетическом случае я никогда не буду использовать такой автомобиль в хэш-таблице или хэшмапе или любой структуре, которая нуждается в хеше, незапамятных времен.

Теперь, почему все еще требуется переопределить hashCode вместе с равными?

Примечание: все ответы, которые я проверяю, включают использование в hashtable/hashmap. Я пробовал экстенсивно, чтобы получить этот ответ, так как запрос не помещает его как дубликат. благодаря

  • 1
    вам не нужно, если вы уверены, что ни одно тело не будет использовать объект этого класса в структуре данных на основе хеша (что обычно не так)
  • 0
    Я мог бы поместить автомобиль в карту (потому что мне нужно хранить его в сеансе). Таким образом, ваш гипотетический случай кажется ложным. Кроме того, вы можете захотеть, чтобы они были Comparable если вы никогда не собираетесь сортировать Cars . И вы можете захотеть переопределить toString() потому что это облегчает запись вещей.
Показать ещё 3 комментария
Теги:
equals
hashcode

2 ответа

3
Лучший ответ

Это общая конвенция:

Если два объекта равны в соответствии с методом equals(Object), то вызов метода hashCode для каждого из двух объектов должен давать одинаковый целочисленный результат.

Однако это не полностью выполнимо.

Бывают моменты, когда вы считаете, что вам не нужно определять hashCode и реализовывать его для вашего объекта, и если вы не используете какую-либо структуру, которая полагается на хеш для хранения или ссылки на нее, вы были бы правы.

Но есть сторонние библиотеки, в которых ваш объект может соприкасаться, и они вполне могут использовать Map или Set чтобы выполнять свою работу, и у них было бы ожидание, что вы следовали правилам.

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

  • 0
    Это политкорректная версия моего ответа. :) +1 Кстати
  • 0
    Существует ли какая-либо законная причина, по которой объект, который переопределяет equals и не может определить что-либо еще полезное для возврата hashCode() должен позволить ему вернуть значение identityHashCode() а не возвращать константу [, которая привела бы к правильному поведению, даже если это не так очень эффективное поведение]
Показать ещё 1 комментарий
0

Единственные мыслимые типы, которые не смогли бы переопределить метод hashCode в соответствии с hashCode и equals контракту, были бы теми, которые не могут переопределить hashCode [например, потому что базовый класс объявил это final ]. Таким образом, почти никогда не существует никаких причин для типа, чтобы не законно реализовать hashCode(). Даже если тип не может гарантировать, что экземпляры, которые являются неравными, не будут спонтанно становиться равными, автор этого типа может все же законно реализовать hashCode(), выбрав 32-значное значение int [например, 8675309] и реализуя hashCode() как @override int hashCode() { return 8675309; } @override int hashCode() { return 8675309; }. Это позволит всем функциям коллекции на основе хэш-таблицы работать правильно. Хранение очень многих таких элементов в хеш-таблице приведет к серьезному ухудшению производительности, но таблицы хэша с несколькими элементами будут работать очень хорошо и обычно выполнять прилично. В отличие от этого, если вы не переопределите hashCode тогда даже хэш-таблица, скорее всего, будет работать некорректно, если в нее будет сохранен один элемент.

Кстати, в некоторых случаях могут быть преимущества для реализации hashCode даже если они не используют хешированные коллекции. Например, некоторые неизменные типы коллекций, которые поддерживают глубокое сравнение, могут вызывать hashCode() для элементов, хранящихся в нем. Если коллекция велика и/или операции сравнения на элементах, хранящихся в ней, являются дорогостоящими, эффективность тестирования двух коллекций для равенства ("они содержат одинаковые элементы") может быть усилена с помощью трехэтапного процесса:

  1. Сравните совокупный хэш-код из двух коллекций. Если они не равны, нет причин смотреть дальше. Часто будет давать мгновенные результаты, независимо от размера коллекций.

  2. Сравните кэшированные хэш-коды всех элементов. Если содержимое коллекций совпадает, за исключением последних элементов пары, и если сравнение между элементами может быть дорогостоящим (например, элементы представляют собой строки с тысячами символов), это часто исключает необходимость сравнивать все, кроме одного элемента, для равенства [обратите внимание, что если все, кроме одного элемента, совпадают, а его хэш-код отличается, то общий хеш-код будет отличаться, и мы бы не получили этого].

  3. Если все хэш-коды совпадают, тогда вызывается equals для каждой пары элементов, которые не сравниваются с эталонными.

Обратите внимание: если в двух коллекциях содержатся отдельные элементы с одинаковым содержимым, сравнение должно будет глубоко изучить все предметы; hashCode не может ничего сделать, чтобы помочь в этом случае. С другой стороны, в большинстве случаев, когда вещи сравниваются, они не равны, и использование кешированных значений hashCode() может способствовать ускорению заказов по величине в этих случаях.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню