Ответ 1
Это зависит от того, что вы подразумеваете под "правильным". Предполагая, что вы используете hashCode()
всех соответствующих полей equals()
-defining, тогда да, это "правильно". Однако такие формулы, вероятно, не будут иметь хорошего распределения и, следовательно, скорее всего вызовут больше столкновений, чем в противном случае, что окажет отрицательное влияние на производительность.
Вот цитата из Effective Java 2nd Edition, Item 9: Всегда переопределяйте hashCode
, когда вы переопределяете equals
В то время как рецепт в этом элементе дает достаточно хорошие хеш-функции, он не дает современных хеш-функций, а библиотеки Java-платформ не предоставляют такие хэш-функции, как в версии 1.6. Написание таких хеш-функций - это тема исследования, которую лучше всего оставлять математикам и компьютерным ученым. [... Тем не менее], методы, описанные в этом пункте, должны быть адекватными для большинства приложений.
Это может не потребовать большой математической силы, чтобы оценить, насколько хороша ваша предлагаемая функция хеширования, но почему даже беспокоиться? Почему бы просто не следовать чему-то, что было доказано на практике адекватно на практике?
Рецепт Джоша Блоха
- Храните некоторое постоянное ненулевое значение, например 17, в переменной
int
, называемойresult
. - Вычислить хэш-код
int
c
для каждого поля:- Если поле
boolean
, вычислите(f ? 1 : 0)
- Если поле является
byte, char, short, int
, вычислить(int) f
- Если поле является
long
, вычислить(int) (f ^ (f >>> 32))
- Если поле является
float
, вычислитьFloat.floatToIntBits(f)
- Если поле является
double
, вычислитеDouble.doubleToLongBits(f)
, тогда хеш получимlong
, как указано выше. - Если поле является ссылкой на объект, и этот класс
equals
метод сравнивает поле путем рекурсивного вызоваequals
, рекурсивно вызываетhashCode
в поле. Если значение поляnull
, верните 0. - Если поле является массивом, рассматривайте его так, как будто каждый элемент является отдельным полем. Если каждый элемент в массиве значителен, вы можете использовать один из методов
Arrays.hashCode
, добавленных в версию 1.5.
- Если поле
- Объедините хэш-код
c
вresult
следующим образом:result = 31 * result + c;
Теперь, конечно, этот рецепт довольно сложный, но, к счастью, вам не нужно повторно его выполнять каждый раз, благодаря java.util.Arrays.hashCode(Object[])
(и com.google.common.base.Objects
предоставляет удобный вариант vararg).
@Override public int hashCode() {
return Arrays.hashCode(new Object[] {
myInt, //auto-boxed
myDouble, //auto-boxed
myRandomClass,
});
}
См. также
-
Object.hashCode()
Не требуется, чтобы, если два объекта неравны в соответствии с методом
equals(java.lang.Object)
, то вызов методаhashCode
на каждом из двух объектов должен производить различные целочисленные результаты. Тем не менее, программист должен знать, что получение отдельных целочисленных результатов для неравных объектов может улучшить производительность хеш-таблиц.