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;
}
}