Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/loops/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 集合框架的HashSet如何识别重复对象?Hashcode和equals如何处理自定义对象?_Java_Arraylist_Collections - Fatal编程技术网

Java 集合框架的HashSet如何识别重复对象?Hashcode和equals如何处理自定义对象?

Java 集合框架的HashSet如何识别重复对象?Hashcode和equals如何处理自定义对象?,java,arraylist,collections,Java,Arraylist,Collections,我查看了一些代码,发现有一个程序扩展了集合的HashSet类。他们创建了自定义的employee对象并将其插入到集合中,而没有实现Comparable或Comparator。他们实现了识别重复的employee对象的逻辑,所以若对象已经存在,他们可以执行更新操作,若对象不存在,他们可以执行插入操作。我试图理解set如何在没有实现Comparable或Comparator接口的情况下识别重复的对象 我也尝试过同样的方法,也尝试过重写Hashcode和equals方法,以了解如何设置比较对象。我发现

我查看了一些代码,发现有一个程序扩展了集合的HashSet类。他们创建了自定义的employee对象并将其插入到集合中,而没有实现Comparable或Comparator。他们实现了识别重复的employee对象的逻辑,所以若对象已经存在,他们可以执行更新操作,若对象不存在,他们可以执行插入操作。我试图理解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");
}
}
class员工{
int-id;
字符串名;
雇员(整数id,字符串名称){
this.id=id;
this.name=名称;
}
@凌驾
公共int hashCode(){
System.out.println(“HashCode:+super.HashCode());
返回super.hashCode();
}
@凌驾
公共布尔等于(对象o){
System.out.println(“等于:+super.Equals(o));
返回super.equals(o);
}
}
类LimitedHashSet扩展了HashSet{
公共布尔加法(雇员e){
如果(!super.add(e)){
返回false;
}
返回true;
}
}
公共类扩展哈希集{
公共静态void main(字符串[]args){
员工e0=新员工(1,“A”);
员工e1=新员工(2,“B”);
LimitedHashSet obj=新的LimitedHashSet();
System.out.println(“添加的元素?”+obj.add(e0)+“\n”);
System.out.println(“添加的元素?”+obj.add(e1)+“\n”);
System.out.println(“添加的元素?”+obj.add(e0)+“\n”);
}
}
Hashcode用于计算bucket,equals方法用于标识其是否等于。那么它在这里是如何工作的呢。请检查下面的输出

输出:

哈希代码:914424520 添加元素?真的

哈希代码:110718392 添加元素?真的

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

从根本上说,没有魔法

HashSet
和所有基于JDK哈希的集合都盲目地使用对象的
hashCode
equals
定义的实现来确定对象是否相同。他们只调用
hashCode
equals
方法,不管这些方法如何工作,这就是散列集合所使用的

使用
hashCode
方法的一部分——首先是基于散列的数据结构的一部分——是为了使基于散列的集合甚至不必麻烦调用
equals
方法来检查两个对象是否相同。如果散列不相同,那么对象肯定不相等。因此,如果需要,它将调用您已重写的
equals
方法,但在您的代码中,它不需要麻烦调用
equals
。此外,它还在调用
equals
方法之前检查引用相等性,因为如果两个对象是
=
,那么它们肯定是
.equals


当前,您正在添加两次
e0
。通过引用相等,
e0==e0
,这样它就不用麻烦调用
.equals
——它只找到匹配的条目,检查它们是否引用相等,并保留现有条目而不添加新元素。顺便说一下,这是正确的行为,因为
e0
是自身的副本。

@AndyTurner:代码在最后一行调用的是
obj.add(e0)
,而不是
obj.add(e3)
@Aks1316您是想第二次添加
e3
而不是
e0
吗?另外:您认为在
LimitedHashSet
中重写
add
有什么作用?它看起来相当于只调用
returnsuper.add(e)@AndyTurner无需再次添加e0。如果我添加e3,它将返回true,并将e3添加到set,而不会出现任何问题。但如果我试图再次添加e0,它不会将其添加到集合中,并向我提供输出中显示的结果false。@AndrewS这在多个级别上是误导性的。密钥是
员工
,而不是其
哈希代码
。鉴于上述实现,具有相同属性值的Employee对象当前具有不同的哈希代码。@AndyTurner:不确定您的意思。无论文档是否这样说,JDK实现都是这样做的,因为它假定您的实现符合合同,这就是OP的程序不打印“Equals:…”的原因