收集框架的HashSet如何识别重复的对象? Hashcode和equals如何与自定义对象一起使用?

时间:2019-05-06 16:53:42

标签: java arraylist collections

我正在看一些代码,找到了一个扩展了HashSet类集合的程序。他们创建了自定义员工对象并插入到Set中,而没有实现Comparable或Comparator。他们实施了逻辑来识别重复的员工对象,因此如果对象已经存在,则可以执行更新操作(如果不存在对象),则可以执行插入操作。我试图了解set如何在没有实现Comparable或Comparator接口的情况下识别重复的对象。

我尝试了相同的方法,还尝试重写Hashcode和equals方法,以了解如何设置比较对象。我发现一件事是,当我添加相同的对象以设置其生成相同的哈希码时。但是它没有调用我已经覆盖的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方法标识其是否等于。那么它在这里如何工作。请检查下面的输出。

输出:

哈希码:914424520 添加元素?是

哈希码:110718392 添加元素?是

哈希码:914424520 添加元素?错误

1 个答案:

答案 0 :(得分:4)

根本上,没有魔术。

HashSet和所有基于JDK哈希的集合盲目地使用hashCodeequals定义的实现来确定对象是否相同。他们只是调用hashCodeequals方法,但是这些方法都起作用,这就是哈希集合的用途。

使用hashCode方法的部分要点-首先是基于散列的数据结构的要点-是使不太可能基于哈希的集合甚至不得不费心调用equals方法来检查两个对象是否相同。如果哈希值不相同,则对象肯定不相等。因此,它会调用您需要重写的equals方法,但是在您的代码中,它无需费心调用equals。此外,它还会在调用equals方法之前检查引用的相等性,因为如果两个对象是==,那么它们肯定是彼此.equals

当前,您两次添加e0。通过引用相等,e0 == e0,所以它不会打扰.equals -它只是找到匹配的条目,检查它们是否等于引用,并保留现有条目而无需添加新元素。顺便说一下,这是正确的行为,因为e0是其自身的副本。