Реализуйте равные с Set - PullRequest
       4

Реализуйте равные с Set

2 голосов
/ 27 сентября 2011

У меня есть этот класс:

private static class ClassA{
int id;
String name;

public ClassA(int id, String name){
    this.id= id;
    this.name = name;
}

@Override
public boolean equals(Object o) {
    return ((ClassA)o).name.equals(this.name);
}   

}

Почему это основное печатает 2 элемента, если я перезаписываю метод, равный в ClassA, чтобы сравнить только имя?

public static void main(String[] args){
    ClassA myObject = new ClassA(1, "testing 1 2 3");
    ClassA myObject2 = new ClassA(2, "testing 1 2 3");    

    Set<ClassA> set = new HashSet<ClassA>();
    set.add(myObject);
    set.add(myObject2);   
    System.out.println(set.size()); //will print 2, but I want to be 1!
}

Если я загляну в документацию Set Java :

Коллекция, которая не содержит повторяющихся элементов. Более формально, множества не содержат пары элементов e1 и e2, таких как e1.equals (e2), и не более одного нулевого элемента. Как следует из его названия, этот интерфейс моделирует абстракцию математического набора.

Так что, очевидно, мне нужно только переопределить equals, однако я слышал, что мне также нужно переопределить хеш-код, но почему?

Ответы [ 2 ]

8 голосов
/ 27 сентября 2011

У них разные хеши, потому что вы не переопределяете hashCode. Это означает, что они были помещены в два разных сегмента в HashSet, поэтому их никогда не сравнивали с равными.

Я бы добавил

public int hashCode() {
    return name.hashCode();
}

Идентификатор уведомления не используется в hashCode, потому что он также не используется в равных.

(PS Я также хотел бы отметить иронию наличия идентификатора, который не используется в равенствах. Это просто забавно. Обычно все наоборот: идентификатор - это единственное, что в равенствах!)

3 голосов
/ 27 сентября 2011

Поскольку вы также не переопределяете hashCode().

программисты должны учитывать, что любой класс, который переопределяет Object.equals метод , также должен переопределять Object.hashCode метод для выполнения генерального контракта по методу Object.hashCode.В частности, c1.equals(c2) подразумевает, что c1.hashCode()==c2.hashCode().

http://download.oracle.com/javase/6/docs/api/java/util/Collection.html

И:

Общий контракт hashCode:

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

  • Если два объекта равны в соответствии с методом equals (Object), то вызов метода hashCode для каждого из двух объектов должен привести к одному и тому же целочисленному результату.

  • Не требуется, чтобы, если два объекта были неравны в соответствии с методом equals (java.lang.Object), то вызов метода hashCode для каждого из двух объектов должен давать различное целое числоРезультаты.Однако программист должен знать, что выдача различных целочисленных результатов для неравных объектов может повысить производительность хеш-таблиц.

http://download.oracle.com/javase/6/docs/api/java/lang/Object.html#hashCode()

...