2015-03-17 6 views
1

У меня есть класс, который, по конкретизации, создает уникальный идентификатор для своих объектов, как так:Является ли это плохой практикой равными() экземплярами класса только их уникальным идентификатором экземпляра?

public class Foo { 

    private final static AtomicInteger UNIQUE_ID = new AtomicInteger(0); 
    private final int id; 
    private final String name;   
    private final int hashcode; 
    public Foo(String name) { 
     id = UNIQUE_ID.GetAndIncrement(); 
     this.name = name; 
     int result = 17; 
     int result = 31 * result + id; 
     int result = 31 * result + name.hashCode(); 
     hashcode = result; 
    } 
    public int getInstanceID() { return id; } 

Теперь я хочу, чтобы реализовать хэш-код и приравнивает этот путь:

public boolean equals(Object obj) { 

     if (obj == this) 
      return true; 
     if (!(obj instanceof Foo)) 
      return false; 

     Foo other = (Foo) obj; 
     return other.getInstanceID == getInstanceID(); 
    } 

    public int hashCode() { return hashcode; } 
} 

она считается плохой если я просто сравню идентификатор объектов, относящихся к любому другому полю, который может отличаться от одного Foo istance другому? Кроме того, следует ли все-таки рассматривать каждое поле в функции hashcode или просто использовать идентификатор?

ответ

0

Хорошо. Контракт идет следующим образом: Если два объекта равны, они должны иметь одинаковые hashCode. У вас нет Overridden hashCode(), так что вы можете иметь 2 одинаковых объекта с другим хэш-кодом, что неверно. переопределить hashcode(), чтобы присоединиться к контракту, то он мог бы просто быть в порядке.

+0

Да, я знаю о контракте hashCode(), и я, конечно, внедрил его. Итак, моя функция hashcode должна использовать все поля, если я их реализую? int result = 17; result = 31 * result + id; result = 31 * result + name.hashCode(); – Jan

+2

@Jan - Это улов. Ваш 'hashCode()' должен следовать 'equals()' i.e, * контракт не указывает, какие все поля должны быть включены *. 'return 5' - это допустимая реализация' hashCode() '. Единственное, что имеет значение, - это * для любых двух экземпляров 'x' и' y', если 'x.equals (y)' истинно, тогда 'x' и' y' должны иметь один и тот же 'hashCode' * – TheLostMind

+0

Итак, я может легко просто вернуть instanceID с помощью функции hashCode, и было бы прекрасно, потому что я знаю, что каждый идентификатор класса будет уникальным? Или должны ли хэш-коды быть глобально уникальными, если это возможно? – Jan

0

Лучшая практика - реализовать функцию hashCode таким образом, чтобы она равномерно распределяла объекты в коллекции (хэш-таблице). Объекты, которые производят один и тот же хэш-код, переходят в одно и то же ведро. Задача функции hashCode - идентифицировать ведро.

Если у вас есть плохая функция, которая возвращает одинаковое значение для всех, то представьте, что все объекты хранятся в одном ведре. Это затрудняет работу коллекции, поскольку она должна проходить через каждый объект и запускать метод equals на них, пока не найдет правильный, если он доступен.

Когда у вас есть хорошая функция hashCode, тогда различные объекты идентифицируются отдельными ковши. Поэтому меньше объектов в данном ковше, что означает необходимость поиска меньше.

Это хорошая идея использовать свойства вашего объекта, чтобы однозначно идентифицировать его.