试写出下列代码的运行结果
HashSet<Person> set = new HashSet();
Person p1 = new Person(1001,"AA");
Person p2 = new Person(1002,"BB");
set.add(p1);
set.add(p2);
p1.name = "CC";
set.remove(p1);
System.out.println(set);
set.add(new Person(1001,"CC"));
System.out.println(set);
set.add(new Person(1001,"AA"));
System.out.println(set);
Person类如下
public class Person {
public int id;
public String name;
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Person person = (Person) o;
return id == person.id &&
Objects.equals(name, person.name);
}
@Override
public int hashCode() {
return Objects.hash(id, name);
}
@Override
public String toString() {
return "Person{" +
"id=" + id +
", name='" + name + '\'' +
", hashCode='"+hashCode()+'\''+
'}';
}
public Person(int id, String name) {
this.id = id;
this.name = name;
}
}
很有意思啊,先看下运行结果
根据运行结果可以看到remove语句并没有执行成功,但是为什么可以add CC,AA两个对象进来呢?不是已经重写equals和hashCode方法了吗?
让我们从头开始分析
HashSet<Person> set = new HashSet();
Person p1 = new Person(1001,"AA");
Person p2 = new Person(1002,"BB");
p1,p2此时的hash值分别为34072,34135
set.add(p1); // 按照 hash = 34072 存放p1
set.add(p2); // 按照 hash = 34135 存放p2
这个时候add是根据此时的hash值存放
p1.name = "CC";
p1 hash值变为34136,但是在set中,p1的存放位置仍然是34072
set.remove(p1);
当我们尝试remove p1的时候,是根据p1的hash值在set中查找是否有hash值相等的对象,有则进一步判断
这一个if就过不了
很显然set中34136并没有存放数据,所以remove失败了,p1自然没有被移除
此时的打印结果为
[Person{id=1002, name=‘BB’, hashCode=‘34135’}, Person{id=1001, name=‘CC’, hashCode=‘34136’}]
set.add(new Person(1001,"CC"));
当我们尝试添加一个这个对象的时候,尽管内容相同,但是还是可以添加成功
这个对象的hash值为34136,和此时p1的hash值相同,但是!! 此时的add是根据34136来add,set中34136并没有存放对象,p1存放在34072里面,并没有产生冲突,所以添加成功了!
[Person{id=1002, name=‘BB’, hashCode=‘34135’}, Person{id=1001, name=‘CC’, hashCode=‘34136’}, Person{id=1001, name=‘CC’, hashCode=‘34136’}]
set.add(new Person(1001,"AA"));
此时hash值与34072相等,p1确实存放在34072里面,但是equals的结果并不相等,仍然可以放入
[Person{id=1002, name=‘BB’, hashCode=‘34135’}, Person{id=1001, name=‘CC’, hashCode=‘34136’}, Person{id=1001, name=‘CC’, hashCode=‘34136’}, Person{id=1001, name=‘AA’, hashCode=‘34072’}]
所以最终结果就是上面这样了
这道题目告诉我们,尽量不要对set,map中的对象进行修改