Зависит от того, что вы подразумеваете под «правильным». Предполагая, что вы используете hashCode()
всех соответствующих equals()
-определяющих полей, тогда да, это "правильно". Однако такие формулы, вероятно, не будут иметь хорошего распределения и, следовательно, могут вызвать больше коллизий, чем в противном случае, что отрицательно скажется на производительности.
Вот цитата из Effective Java 2nd Edition , пункт 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
для каждого из этих двух объектов должен давать различные целочисленные результаты. Однако, программист должен знать, что выдача различных целочисленных результатов для неравных объектов может улучшить производительность хеш-таблиц.