HashSet的经典面试题

import java.util.HashSet;

public class TestHashSet {
	public static void main(String[] args) {
		HashSet<Person> set = new HashSet<Person>();
		Person p1 = new Person("AA",1001);
		Person p2 = new Person("BB",1002);
		
		set.add(p1);
		set.add(p2);
		System.out.println(set);
		
		p1.name = "CC";//第一处 [Person [name=CC, id=1001], Person [name=BB, id=1002]]
		set.remove(p1);// 第二处
		System.out.println(set);
		
		set.add(new Person("CC",1001));// 第三处
		System.out.println(set);
		set.add(new Person("AA",1001));// 第四处
		System.out.println(set);
	}
}

Output:

[Person [name=AA, id=1001], Person [name=BB, id=1002]]
[Person [name=CC, id=1001], Person [name=BB, id=1002]]
[Person [name=CC, id=1001], Person [name=CC, id=1001], Person [name=BB, id=1002]]
[Person [name=CC, id=1001], Person [name=CC, id=1001], Person [name=AA, id=1001], Person [name=BB, id=1002]]

分析:
第一处:当修对象p1的name属性时,修改了对应堆内具体对象的值。而集合中存放的是对象的引用,所以在当修改后集合中的值也会被修改。但是在HashSet底层是HashMap实现的,而p1对象所占的hash桶任然是未修改前的对象的hash值所对应的桶。
第二处:此时p1对象已经被修改了,remove()是根据修改后的对象的hash值,找对应的位置,因此此时删除时对应的位置没有值,所以此时没有认出任何数据。
第三处:当加入new Person(“CC”,“1001”)对象时,虽然此对象与p1对象值完全相等,但是添加时,添加到了该对象所对应的hash桶,而此时的位置与p1不是同一个位置,因为p1是根据修改之前的hash值放入对应的has桶内的,因此他们不冲突。
第四处:当加入new Person(“AA”,1001)时,该值与未修改前的p1值完全相等,所以对应的hash桶也是同一个位置,添加时找到对应的桶位置后,发现已经有一个对象,然后用equals方法比较值,此时值不相等,因此不产生冲突,依然可以加入到HashSet中。
Person类

/**
 * Person类
 * @author minghai
 *
 */
public class Person {
	String name;
	int id;
	public Person(String name, int id) {
		super();
		this.name = name;
		this.id = id;
	}
	public Person() {
		super();
	}
	@Override
	public String toString() {
		return "Person [name=" + name + ", id=" + id + "]";
	}
	
	@Override
	public boolean equals(Object obj) {
		if(!(obj instanceof Person)) {
			return false;
		}
		Person p = (Person) obj;
		return this.id == p.id && this.name.equals(p.name);
	}
	@Override
	public int hashCode() {
		int result = 17;
		result = result * 37 + id;
		result = result * 37 + name.hashCode();
		return result;
	}
}
  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值