Как HashSet структуры коллекции идентифицирует дубликаты объектов?Как Hashcode и equals работают с пользовательскими объектами? - PullRequest
4 голосов
/ 06 мая 2019

Я посмотрел какой-то код и нашел одну программу, в которой они расширили класс коллекции HashSet. Они создали пользовательские объекты сотрудников и вставили их в Set без реализации Comparable или Comparator. Они реализовали логику для идентификации дублирующего объекта сотрудника, поэтому, если объект уже существует, они могут выполнить операцию обновления, если объект отсутствует, они могут выполнить операцию вставки. Я пытался понять, как set будет идентифицировать дублированный объект без реализации интерфейса Comparable или Comparator.

Я попробовал то же самое, а также попытался переопределить Hashcode и метод equals, чтобы понять, как установить сравнение объектов. Одна вещь, которую я обнаружил, это то, что я добавляю один и тот же объект для установки его генерации того же Hashcode Но он не вызывает метод equals, который я переопределил.

class Employee {
    int id;
    String name;

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

    @Override
    public int hashCode() {
        System.out.println("HashCode : " + super.hashCode());
    return super.hashCode();
    }

    @Override
    public boolean equals(Object o) {
        System.out.println("Equals : " + super.equals(o));
    return super.equals(o);
    }
}

class LimitedHashSet extends HashSet<Employee> {
    public boolean add(Employee e) {
        if(!super.add(e)){
            return false;
        }
    return true;
    }
}
public class ExtendingHashSet {

    public static void main (String[] args) {
    Employee e0 = new Employee(1,"A");
    Employee e1 = new Employee(2,"B");

    LimitedHashSet obj = new LimitedHashSet();

    System.out.println("Element added ? " + obj.add(e0) + "\n");
    System.out.println("Element added ? " + obj.add(e1) + "\n");
    System.out.println("Element added ? " + obj.add(e0) + "\n");
}
}

Хэш-код используется для вычисления сегмента, а метод equals определяет его равные или нет. Так как это работает здесь. Пожалуйста, проверьте вывод ниже.

Выход:

HashCode: 914424520 Элемент добавлен? правда

HashCode: 110718392 Элемент добавлен? правда

HashCode: 914424520 Элемент добавлен? ложь

1 Ответ

4 голосов
/ 06 мая 2019

По сути, там нет магии.

HashSet и все основанные на хешах коллекции JDK вслепую используют реализации определений hashCode и equals для ваших объектов, чтобы определить, являются ли объекты одинаковыми или нет. Они просто вызывают методы hashCode и equals, и как бы они ни работали, именно это и используют хеш-коллекции.

Часть смысла использования метода hashCode - в первую очередь части смысла структур данных на основе хеша - состоит в том, чтобы сделать маловероятным то, что на основе хеша коллекция даже вынуждена вызывать метод equals, чтобы проверить, совпадают ли два объекта. Если хэши не совпадают, то объекты определенно не равны. Так что будет вызывать метод equals, который вы переопределили, если это необходимо, но в вашем коде не нужно беспокоиться о вызове equals. Кроме того, он также проверяет равенство ссылок перед вызовом методов equals, потому что если два объекта равны ==, то они определенно .equals друг для друга.

В настоящее время вы добавляете e0 дважды. По равенству ссылок e0 == e0, поэтому он не беспокоится о вызове .equals - он просто находит соответствующую запись, проверяет, что они равны по ссылке, и сохраняет существующую запись без добавления нового элемента. Кстати, это правильное поведение, поскольку e0 является его дубликатом.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...