Java 集合框架的HashSet如何识别重复对象?Hashcode和equals如何处理自定义对象?
我查看了一些代码,发现有一个程序扩展了集合的HashSet类。他们创建了自定义的employee对象并将其插入到集合中,而没有实现Comparable或Comparator。他们实现了识别重复的employee对象的逻辑,所以若对象已经存在,他们可以执行更新操作,若对象不存在,他们可以执行插入操作。我试图理解set如何在没有实现Comparable或Comparator接口的情况下识别重复的对象 我也尝试过同样的方法,也尝试过重写Hashcode和equals方法,以了解如何设置比较对象。我发现,当我添加相同的对象以设置其生成相同的哈希代码时。但它并没有调用我重写的equals方法Java 集合框架的HashSet如何识别重复对象?Hashcode和equals如何处理自定义对象?,java,arraylist,collections,Java,Arraylist,Collections,我查看了一些代码,发现有一个程序扩展了集合的HashSet类。他们创建了自定义的employee对象并将其插入到集合中,而没有实现Comparable或Comparator。他们实现了识别重复的employee对象的逻辑,所以若对象已经存在,他们可以执行更新操作,若对象不存在,他们可以执行插入操作。我试图理解set如何在没有实现Comparable或Comparator接口的情况下识别重复的对象 我也尝试过同样的方法,也尝试过重写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");
}
}
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:…”的原因