У меня есть следующий класс java:
public class Person{
String name; //a unique name
Long DoB; //a unique time
.
.
.
@Override
public int hashCode(){
return name.hashCode() + DoB.hashCode();
}
}
Является ли мой метод hashCode правильным (т.е. вернет ли он уникальное количество всех комбинаций.
У меня такое чувство, что я что-то пропустил.
Вы также можете использовать что-то более свободно и более NPE-пуленепробиваемое, как Google Guava:
@Override
public int hashCode(){
return Objects.hashCode(name, DoB);
}
@Override
public boolean equals(Object o) {
if ( this == o ) {
return true;
}
if ( o == null || o.getClass() != Person.class ) {
return false;
}
final Person that = (Person) o;
return Objects.equal(name, that.name) && Objects.equal(DoB, that.DoB);
}
Редактировать:
IntelliJ IDEA и Eclipse могут генерировать более эффективные hashCode()
и equals()
.
Вы можете позволить java.util.Arrays
сделать это за вас:
return Arrays.hashCode(new Object[]{ name, DoB });
Помимо очевидного, то есть, вы можете захотеть реализовать метод equals
...
int
См. Bloch Эффективная Java # 9.
Но вы должны начать с начального значения (так что последующие нулевые значения являются значительными) и объединить поля, которые применяются к результату, вместе с множителем, чтобы порядок был значительным (так что аналогичные классы будут иметь очень разные хэши).
Кроме того, вам придется обрабатывать такие вещи, как длинные поля и строки, немного разные. например, для длин:
(int) (field ^ (field>>>32))
Итак, это означает что-то вроде:
@Override public int hashCode() {
int result = 17;
result += name.hashCode() == null ? 0 : name.hashCode();
result = 31 * result + (int) (DoB ^ (DoB >>> 32));
return result;
}
31 немного магия, но нечетные простые числа могут облегчить компилятору оптимизацию математики для вычитания сдвига. (Или вы можете сделать смену-вычитание самостоятельно, но почему бы не позволить компилятору сделать это.)
Реализация хеш-кода выполнена правильно и правильно. Было бы лучше, если бы вы следовали любым предложениям, сделанным другими людьми, но это удовлетворяет контракту на hashCode
, и столкновения не особенно вероятны, хотя их можно было бы сделать менее вероятными.
обычно хэш-код создается так:
@Override
public int hashCode(){
return name.hashCode() ^ DoB.hashCode();
}
но важно помнить, когда используется метод hashcode, это его использование. использование метода hashcode заключается в том, чтобы поместить другой объект в разные ведра в хэш-таблицу или другую коллекцию, используя hashcode. как таковой, он импотентен иметь метод, который дает разные ответы на разные объекты в низком времени выполнения, но не обязательно должен быть другим для каждого элемента, хотя это лучше.
Этот хэш используется другим кодом при хранении или манипулировании экземпляром - значения предназначены для равномерного распределения для различных входов для использования в кластеризации. Это свойство важно для производительности хеш-таблиц и других структур данных, которые хранят объекты в группах ("ведра") на основе их вычисленных значений хэш-функции
а также
Общий контракт для переопределенных реализаций этого метода заключается в том, что они ведут себя так же, как и один метод equals() объекта: данный объект должен последовательно сообщать о том же значении хэша (если он не изменен так, что новая версия больше не будет считается "равным" для старого), и что два объекта, равные равенствам(), равны, должны сообщать о том же значении хэш-функции.
equals
переопределение. Возможно, вы захотите умножить длинный на что-то странное, например, 31.hash(a) + hash(b) != hash(a+b)
. хотя это не совсем легко сделать, кто-то может найти совершенно другую строку SINGLE, которая хэширует то же значение, что и объединенный хэш (a) + hash (b).