2010-12-14 3 views
7

Для класса, чьи поля являются исключительно примитивно, напр .:Переопределение hashCode() - это достаточно хорошо?

class Foo 
{ 
    int a; 
    String b; 
    boolean c; 
    long d; 

    boolean equals(Object o) 
    { 
     if (this == o) return true; 
     if (!(o instanceof Foo)) return false; 
     Foo other = (Foo) o; 
     return a == other.a && b.equals(other.b) && c == other.c && d = other.d; 
    } 
} 

Является ли это разумно «достаточно хорошо» способ писать hashCode()?

boolean hashCode() 
{ 
    return (b + a + c + d).hashCode(); 
} 

То есть, я построить String из одних и тех же областях, что equals() использования, а затем просто использовать String#hashCode().

Редактировать: Я обновил свой вопрос, чтобы включить поле long. Как следует обрабатывать long в hashCode()? Просто позвольте этому переполнению int?

+0

Хотя он не очень эффективен, он должен работать нормально, потому что любые два экземпляра со всеми одинаковыми внутренними значениями будут иметь один и тот же хэш-код. – Gabe

+0

Он будет работать правильно, я не знаю о проблеме с производительностью, но он, безусловно, будет работать. Если вы хотите пойти дальше, прочитайте: http://www.ibm.com/developerworks/java/library/j-jtp05273.html – Necronet

+0

Просто используйте [honsCodeBuilder] commons-lang] (http://commons.apache.org/ lang/api-2.5/org/apache/commons/lang/builder/HashCodeBuilder.html) и никогда не придется беспокоиться об этом типе –

ответ

7

Ваш хэш-код удовлетворяет тому, что если два объекта равны, то их хэш-коды должны быть равны. Таким образом, это «достаточно хорошо». Однако довольно просто создать коллизии в хеш-кодах, что ухудшит производительность хэш-структур данных.

Я бы реализовать его немного по-другому, хотя:

public int hashCode() { 
    return a * 13 + b.hashCode() * 23 + (c? 31: 7); 
} 

Вы должны проверить documentation for the hashCode() method из Object. В нем описаны вещи, которые должен удовлетворять хэш-код.

+0

Я понимаю контракт для 'equals()' и 'hashCode()'. То, что я ищу, - это минималистичный, идиот-устойчивый, не удивительный способ выполнить контракт. Ваш код кажется достаточно разумным. Не могли бы вы объяснить причину умножения на простые числа? Кроме того, я обновил свой вопрос: как мне работать с «длинными» полями? –

+3

@Matt - «минимальное усилие, путь« идиот-устойчивый »использует вашу среду IDE для генерации метода. Например, Netbeans генерирует один из моих классов:' int hash = 5; hash = 37 * hash + (int) (this. id^(this.id >>> 32)); return hash; ' –

+1

@Coronatus: hmm, good point. Я забыл о' Alt + Shift + S' (Eclipse) –

0

Это полностью зависит от того, как будут выглядеть ваши данные. В большинстве случаев это было бы хорошим подходом. Если у вас часто будет b конец с номером, то вы получите несколько повторяющихся кодов для неравных объектов, как показывает ответ JacobM. Если вы заранее знаете, что b в конце концов не будет иметь числового значения в конце, то это разумный алгоритм хэширования.