【问题标题】:Duplicate custom objects are getting added to Hashset重复的自定义对象被添加到 Hashset
【发布时间】:2019-04-19 11:31:38
【问题描述】:

我有一个 Employee 类,它有 2 个属性 id 和 name。我正在覆盖下面给出的 hashcode 和 equals 方法。

Employee.java:

import java.util.Objects;

public class Employee {

    private int id;
    private String name;

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    @Override
    public int hashCode() {
        return Objects.hash(id, name);
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj)
            return true;
        if (obj == null)
            return false;
        if (getClass() != obj.getClass())
            return false;
        Employee other = (Employee) obj;
        if (id != other.id)
            return false;
        if (name == null) {
            if (other.name != null)
                return false;
        } else if (!name.equals(other.name))
            return false;
        return true;
    }

    @Override
    public String toString() {
        return "Employee [id=" + id + ", name=" + name + "]";
    }
}

现在我有一个测试类,我在其中创建一个名为“Chris Gayle”的员工类对象并将其添加到 HashSet。之后,我将这个现有员工对象的名称修改为“Kieron Pollard”,并将这个修改后的员工对象再次添加到 hashset。

TestSet.java

import java.util.HashSet;
import java.util.Set;

public class TestSet {

 public static void main(String[] args) {
     Set<Employee> hashSet = new HashSet<Employee>();

     Employee emp1 = new Employee();
     emp1.setId(1);
     emp1.setName("Chris Gayle");

     hashSet.add(emp1);

     System.out.println(hashSet);

     emp1.setName("Kieron Pollard");
     hashSet.add(emp1);
     System.out.println(hashSet.size());
     System.out.println(hashSet);
}

}

当我打印 hashset 的内容时,我给出了相同的员工对象两次,如下所示。

[Employee [id=1, name=Chris Gayle]]
2
[Employee [id=1, name=Kieron Pollard], Employee [id=1, name=Kieron Pollard]]

因为,set 不允许重复元素,但在输出中我们在上述场景中得到了重复元素。那么,处理这种行为的正确方法是什么。

【问题讨论】:

  • 为什么是java-ee 标签?您的问题与 Java 企业版服务器-客户端互选项直接有什么关系?
  • 我已经edited 您的问题并更新了标签。请注意标签,因为它们和您的问题标题是您问题中最重要的部分,有助于吸引合适的专家对其进行审查

标签: java hashset hashcode


【解决方案1】:

你在这里开枪打死了自己。

@Override
public int hashCode() {
    return Objects.hash(id, name);
}

如果hashCodeidname 定义并且您在再次将对象添加到HashSet 之前更改名称,您显然会得到一个重复的条目。提醒:对象的唯一性由hashCode 决定——这就是HashSet 用来确定对象是否已经在Set 中。

您的独特性标准是什么?如果 id 是唯一的,请在 hashCode 中仅使用 id

@Override
public int hashCode() {
    return Objects.hash(id);
}

【讨论】:

    【解决方案2】:

    感谢您提出这个问题。你应该看看HashSet 是如何实现的。您的示例还很好地说明了为什么首选不变性。

    这就是正在发生的事情。

    • 您创建了一个将其添加到HashSet 的对象。
    • HashSet 用对象的哈希值存储了对对象的引用。假设哈希为 10(对于 id = 1,name = Chris Gayle)
    • 现在,当您更改对象时,HashSet 不知道您对对象所做的更改。它只保存引用,但对象的哈希值已更改。让我们说 20(对于 id = 1,name = Kieron Pollard)。
    • equals 和 dashcode 之间存在关系。如果对象的哈希码相等,则对象可能相等。哈希码不同,则对象永远不会相等。所以按照这个逻辑,当你添加相同的对象或第二次添加一个新条目时,HashSet 添加了一个新条目。

    如果您尝试使用new HashSet&lt;&gt;(hashSet) 创建一个新的 HashSet,那么您只会看到一个对象。

    【讨论】:

    • 两者相同。这里的实现是关于散列的,所以我解释的是散列的关系。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-05-11
    • 2018-11-16
    • 1970-01-01
    • 2015-09-07
    • 1970-01-01
    • 1970-01-01
    • 2023-03-26
    相关资源
    最近更新 更多