重复的自定义对象被添加到 Hashset
Duplicate custom objects are getting added to Hashset
我有一个 Employee class 有 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 + "]";
}
}
现在我有一个测试 class,我在其中创建名称为 "Chris Gayle" 的员工 class 的对象并将其添加到 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 不允许重复元素,但在输出中我们在上面的场景中得到了重复元素。那么,处理这种行为的正确方法是什么。
你是搬起石头砸自己的脚。
@Override
public int hashCode() {
return Objects.hash(id, name);
}
如果 hashCode
由 id
和 name
定义并且您在再次将对象添加到 HashSet
之前更改名称,您显然会得到双重输入。提醒:对象的唯一性由 hashCode
决定 - 这就是 HashSet
用来确定对象是否已经在 Set
.
中
您的独特性标准是什么?如果 id
是唯一的,请仅在 hashCode
中使用 id
。
@Override
public int hashCode() {
return Objects.hash(id);
}
感谢您提出这个问题。您应该看看 HashSet
是如何实现的。您的示例还很好地说明了为什么首选不变性。
这是正在发生的事情。
- 您创建了一个对象并将其添加到
HashSet
。
HashSet
使用对象的哈希值存储对对象的引用。假设哈希为 10(对于 id = 1,name = Chris Gayle)
- 现在,当您更改对象时,
HashSet
不知道您对该对象所做的更改。它仅包含引用,但对象的哈希值已更改。让我们说 20(对于 id = 1,name = Kieron Pollard)。
- equals 和 dashcode 之间有关系。如果对象的哈希码相等,则对象可能相等。哈希码不同,那么对象永远不会相等。所以按照这个逻辑,HashSet在你添加同一个对象的时候或者第二次添加了一个新的条目。
如果您尝试使用 new HashSet<>(hashSet)
创建一个新的 HashSet,那么您将只会看到一个对象。
我有一个 Employee class 有 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 + "]";
}
}
现在我有一个测试 class,我在其中创建名称为 "Chris Gayle" 的员工 class 的对象并将其添加到 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 不允许重复元素,但在输出中我们在上面的场景中得到了重复元素。那么,处理这种行为的正确方法是什么。
你是搬起石头砸自己的脚。
@Override
public int hashCode() {
return Objects.hash(id, name);
}
如果 hashCode
由 id
和 name
定义并且您在再次将对象添加到 HashSet
之前更改名称,您显然会得到双重输入。提醒:对象的唯一性由 hashCode
决定 - 这就是 HashSet
用来确定对象是否已经在 Set
.
您的独特性标准是什么?如果 id
是唯一的,请仅在 hashCode
中使用 id
。
@Override
public int hashCode() {
return Objects.hash(id);
}
感谢您提出这个问题。您应该看看 HashSet
是如何实现的。您的示例还很好地说明了为什么首选不变性。
这是正在发生的事情。
- 您创建了一个对象并将其添加到
HashSet
。 HashSet
使用对象的哈希值存储对对象的引用。假设哈希为 10(对于 id = 1,name = Chris Gayle)- 现在,当您更改对象时,
HashSet
不知道您对该对象所做的更改。它仅包含引用,但对象的哈希值已更改。让我们说 20(对于 id = 1,name = Kieron Pollard)。 - equals 和 dashcode 之间有关系。如果对象的哈希码相等,则对象可能相等。哈希码不同,那么对象永远不会相等。所以按照这个逻辑,HashSet在你添加同一个对象的时候或者第二次添加了一个新的条目。
如果您尝试使用 new HashSet<>(hashSet)
创建一个新的 HashSet,那么您将只会看到一个对象。