Java Set получает повторяющуюся запись - PullRequest
1 голос
/ 14 декабря 2011

JavaDoc определяет набор как:

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

Чтобы проверить это, я создал очень простую программу:

import java.util.HashSet;

public class CheckHashSet {
    public static void main(String[] args) {
        HashSet<Employee> set = new HashSet<Employee>();
        set.add(new Employee(10));
        set.add(new Employee(10));
        System.out.println(set.size());
        System.out.println(new Employee(10).equals(new Employee(10)));
    }

    private static class Employee implements Comparable<Employee> {
        private final int id;
        public Employee(int id) {
            this.id = id;
        }
        @Override
        public int compareTo(Employee o) {
            return this.id - o.id; 
        }

        @Override
        public boolean equals(Object obj) {
            if(obj instanceof Employee) {
                return compareTo((Employee)obj)==0;
            }
            return false;
        }
    }
}

Вывод программы:

2
true

Это означает, что new Employee(10).equals(new Employee(10)) возвращает true, тогда как set.add(new Employee(10)); set.add(new Employee(10)); добавляет объект дважды.

Что не так с моим кодом?

Ответы [ 4 ]

7 голосов
/ 14 декабря 2011

Ваш Employee класс не переопределяет hashCode - он должен это сделать, чтобы работала любая основанная на хэше коллекция.

Например:

@Override
public int hashCode() {
    return id;
}
4 голосов
/ 14 декабря 2011

Ваш класс нарушает совместный договор по equals() и hashCode():

Обратите внимание, что обычно необходимо переопределять метод hashCode всякий раз, когда переопределяется метод equals, чтобы поддерживать общий контракт для метода hashCode , в котором говорится, что равные объекты должны иметь одинаковые хеш-коды.

В вашем случае равные объекты не обязательно имеют одинаковые хеш-коды. Это то, что сбивает с толку HashSet, поскольку Employees с одним и тем же id может оказаться в разных сегментах и, следовательно, рассматриваться как если бы они не были равны.

Чтобы исправить, переопределите hashCode() [например, просто верните this.id].

1 голос
/ 14 декабря 2011

HashSet основан на хеш-таблице структура данных, поэтому вы должны переопределить методы equals и hashCode в классе Employee, чтобы он работал правильно.

Однако вы можете использовать другую реализацию Set, не основанную на хеш-таблице, такую ​​как TreeSet.

0 голосов
/ 14 декабря 2011

Может быть, здесь ваша проблема return this.id - o.id; вместо этого вы проверяете return this.equals(o), которые возвращают true или false.

...