当前位置: 首页 > 知识库问答 >
问题:

集合框架的HashSet如何识别重复对象?Hashcode和equals如何与自定义对象一起工作?

龙嘉玉
2023-03-14

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

我试过same,也试过重写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");
}
}

Hashcode用于计算bucket,而equals方法标识其相等与否。那么它在这里是如何运作的。请检查下面的输出。

HashCode:914424520添加了元素?假

共有1个答案

刘和玉
2023-03-14

从根本上说,没有魔法。

hashset和所有基于JDK哈希的集合盲目地使用对象的hashcodeequals定义的实现来确定对象是否相同。它们只调用hashcodeequals方法,无论这些方法如何工作,哈希集合都使用这些方法。

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

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

 类似资料:
  • 问题内容: 决定将这些方法包含在java.lang.Object中的背后原因是什么?平等和哈希对于许多类没有意义。 建立两个接口将更加合乎逻辑: 例如,HashSet定义可能看起来像 这将防止出现一个常见的初学者错误-使用项目集而不实现equals / hashCode。 问题答案: 当我们实现一个接口时,我们注入(或接受)该接口定义的合同。 &是两个不同的合同。但是,如果我们仔细观察,就会发现它

  • 考虑下面的代码: 对于上面的代码,输出是:

  • 我试图覆盖提到的方法为我的: MyObject: 如何重写hashcode(),equals()和compareTo()方法? 目前我有以下几点: 我读到通过id比较是不够的,这是对象是数据库的持久实体(见这里)。 此类型的所有对象的名称和编号不是唯一的。 那么我应该如何覆盖它呢? 我还需要比较它里面的hashMap吗? 我很困惑。该对象唯一独特的地方是map myMap,它将在生命周期的后期填充

  • 问题内容: 建议和有时是必要的,即表示值(类 值类 )来覆盖,[和任选]的方法。这些方法返回的值取决于类及其超类的成员变量的全部或子集。为了实现它们正常,你必须了解理论的一点点 散列 和代数和集理论的一点点(不要太多,几乎一切都在explaind 的javadoc 这些方法和有效的Java形式乔希布洛赫。) 在大多数情况下,此方法的实现遵循一个模板,并且IDE(如Eclipse JDT)包括生成它

  • 如果它走路像鸭子,说话像鸭子,样子像鸭子,叫声也像鸭子,那它就是一只鸭子。 对于 Nutz Ioc 来说,它面对的配置文件就是层层嵌套的 "名值对集合",或者说是 Map 集合。 事实上,它是先把整个配置文件解析成 Map 再做判断的。 如果一个 Map 仅包括如下的键,则被认为是一个注入对象: type 对象类型 singleton 是否单例 scope 生命周期范围 events 监听事件 a

  • 我有这样的记录: 它获取default和方法。 如何调整这些方法使其具有自定义行为?假设,我想忽略方法中的。