一道关于HashSet的题目

试写出下列代码的运行结果

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中的对象进行修改

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值