重复的自定义对象将添加到Hashset

问题描述 投票:0回答:2

我有一个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。

test set.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 hashset hashcode
2个回答
3
投票

你在这里射击自己。

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

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

你的独特性标准是什么?如果id意味着独特,请在id中仅使用hashCode

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

2
投票

谢谢你提出这个问题。你应该看看HashSet是如何实现的。您的示例还提供了关于为什么不可变性的首选。

这是正在发生的事情。

  • 您创建了一个将对象添加到HashSet的对象。
  • HashSet使用对象的哈希值存储对象的引用。我们说hash是10(For id = 1,name = Chris Gayle)
  • 现在,当您更改对象时,HashSet不知道您对该对象所做的更改。它仅包含引用,但对象的哈希值已更改。我们说20(id = 1,名字= Kieron Pollard)。
  • equals和dashcode之间存在关系。如果对象的哈希码相等,则对象可以相等。哈希码是不同的,然后对象永远不会相等。因此,通过这种逻辑,当您添加相同对象或第二次时,HashSet添加了一个新条目。

如果您尝试使用new HashSet<>(hashSet)创建新的HashSet,那么您将只看到一个对象。

© www.soinside.com 2019 - 2024. All rights reserved.