Я задаюсь вопросом, какова лучшая практика для записи #hashCode () метод в Java. Хорошее описание может быть найдено здесь. Это настолько хорошо?
Отличный справочник по реализации hashCode ()
описан в книге Эффективная Java . После того, как вы поймете теорию создания хорошей хеш-функции, вы можете проверить HashCodeBuilder на Apache commons lang, который реализует то, что описано в книге. Из документации:
Этот класс позволяет создать хороший метод hashCode для любого класса. Он следует правилам, изложенным в книге Эффективная Java Джошуа Блоха. Написать хороший метод hashCode на самом деле довольно сложно. Этот класс призван упростить процесс.
Как говорит @leonbloy, хорошо это понимать. Однако даже в этом случае один из «лучших» способов - просто позволить вашей среде IDE написать функцию за вас. Это не будет оптимальным при некоторых обстоятельствах - а в некоторых очень редких случаях это даже не будет хорошо - но для большинства ситуаций это легко, повторяемо, без ошибок и настолько хорошо (как хэш-код), насколько это необходимо. быть. Конечно, прочтите документацию и хорошо ее поймите, но не усложняйте ее без необходимости.
Вот цитата из Effective Java 2nd Edition, Item 9: "Always override hashCode
when you override equals
":
Хотя рецепт в этом пункте дает достаточно хорошие хэш-функции, он не дает современных хэш-функций, и библиотеки платформы Java не предоставляют таких хэш-функций по состоянию на релиз 1.6. Написание таких хэш-функций - это тема для исследований, которую лучше оставить математикам и компьютерным ученым. [... Тем не менее,] техники, описанные в этом пункте, должны быть достаточными для большинства приложений".
int
под названием result
int
c
для каждого поля f
, которое определяет equals
:
булевым
, вычислите (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
, верните 0Arrays.hashCode
, добавленных в релизе 1.5c
в result
следующим образом: result = 31 * result + c;
Теперь, конечно, этот рецепт довольно сложен, но, к счастью, вам не придется каждый раз реализовывать его заново, благодаря java.util.Arrays.hashCode(Object[])
.
@Override public int hashCode() {
return Arrays.hashCode(new Object[] {
myInt, //auto-boxed
myDouble, //auto-boxed
myString,
});
}
Начиная с Java 7 есть удобный вариант varargs в java.util.Objects.hash(Object...)
.