如果我们在HashSet中添加两个不同的对象(可变),之后通过调用setter来改变对象的值(使它们相同),大小仍然是hashSet的2个
我无法理解同样的原因:
public static void main(String[] args) {
Employee e = new Employee();
e.setName("Amit");
Employee e1 = new Employee();
e1.setName("Jitender");
Set<Person> hashSet = new HashSet<Person>();
hashSet.add(e);
hashSet.add(e1);
// size of set is >>2
System.out.println("size of set is >>" + hashSet.size());
e1.setName("Amit");
// updated size of set is >>2
System.out.println("updated size of set is >>" + hashSet.size());
}
员工类是:
public class Employee extends Person {
public Employee() {
}
public Employee(String name) {
this.name = name;
}
String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public int hashCode() {
// TODO Auto-generated method stub
return name.hashCode();
}
@Override
public boolean equals(Object obj) {
Employee e = (Employee) obj;
return this.name.equals(e.name);
}
}
答案 0 :(得分:3)
HashSet
无意对其包含的对象的更改做出反应。实际上,文档警告不要将可变对象添加到集合并修改它们。
来自Set
interface documentation:
注意:如果将可变对象用作set元素,则必须非常小心。如果在对象是集合中的元素的同时以影响等于比较的方式更改对象的值,则不指定集合的行为。这种禁令的一个特例是,不允许集合将自身作为一个要素包含在内。
(另一点是HashSet
使用成员的equals()
和hashCode()
方法,这意味着如果您没有为Employee
实施这些方法,则Employee
除非它们是对同一个Employee
对象的两个引用,否则{1}}将不相等。)在您的编辑中,您显示已实现该目标。
在一个实际的“如果我这样做会发生什么?”请注意,如果您查看source code of HashMap
(b / ca HashSet
实现为HashMap
,将您插入的条目映射到虚拟对象),您可以看到只更新了大小当你添加和删除变量时,即使重新调整表以增加容量,也没有相等的检查,所以你的重复对象将保留在你刚刚破坏的那个集合中,做你应该没有的东西一直在做。
答案 1 :(得分:3)
您是如何定义hashCode()
类中的equals()
和Employee
方法的?此外,HashSet
的契约中没有任何内容指定如果集合中的两个可变对象突然具有相同的哈希值,该怎么办,你不能假设它们中的任何一个被自动从集合中移除。
另外,请注意Set
的文档中的note:
如果将可变对象用作集合元素,则必须非常小心。如果在对象是集合中的元素的同时以影响等于比较的方式更改对象的值,则不指定集合的行为。这种禁止的一个特例是,不允许集合将自己作为一个元素包含在内。
答案 2 :(得分:0)
size()
返回集合中的元素数量。由于您不通过调用e1.setName()
来更改集合,因此集合的大小保持不变。
答案 3 :(得分:0)
您在Set中添加了2个不同的对象。即使它们的值相同,它们也是不同的对象。
答案 4 :(得分:0)
它们是使用两个不同的Employee.class实例创建的。因此,即使它们具有相同的属性名称值,它们仍然是不同的对象。除非当然在Employee.class中重写hash和equals,否则相等性基于属性名称。