HashSet 添加元素,首先比较hash值 是否有相同hash,没有则添加成功,有则继续比较equals,如果不同则添加成功,否则不添加。
测试方法,使用一个Java Bean的person类,有name和age两个域,覆写public boolean equals(Object obj) 和public int hashCode() 两个方法,覆写方法中都添加一句输出语句,测试是否该方法被调用/
person类:
package info.dyndns.oszc;
public class Person {
public String name;
public int age;
public Person(String name, int age)
{
this.name = name;
this.age = age;
}
public void print(){
System.out.println(name + age);
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String toString(){
return getName() +".." + getAge();
}
@Override
public boolean equals(Object obj) {
System.out.println("调用equals方法"); //这里打印为了看清程序是否调用了equals方法
if( !(obj instanceof Person)){
return false;
}
Person p =(Person) obj;
return getName().equals(p.getName()) && getAge()==p.getAge();
}
@Override
public int hashCode() {
System.out.println("调用hashCode方法,hash为:"+ getName().hashCode() + getAge()*9); //这里打印为了看清程序是否调用了equals方法
return getName().hashCode() + getAge()*9;
}
}
工具类
package info.dyndns.oszc;
import java.util.*;
public class Utils {
public static <E>void print(E e)
{
System.out.println(e);
}
public static <E>void printElements(Collection<E> al)
{
Iterator<E> it = al.iterator();
while (it.hasNext()){
print(it.next());
}
}
public static <E>void put (Collection al,E e)
{
if (!al.contains(e))
al.add(e);
}
}
测试类,首先添加两个不同的元素
package info.dyndns.oszc;
import java.util.HashSet;
public class HashSetTest {
public void test(){
HashSet<Person> hs = new HashSet<Person>();
hs.add(new Person("zs", 11));
hs.add(new Person("ls", 12));
Utils.printElements(hs);
}
public static void main(String[] args) {
HashSetTest hst = new HashSetTest();
hst.test();
}
}
output:
调用hashCode方法,hash为:389799
调用hashCode方法,hash为:3463108
ls..12
zs..11
显然调用了两次hashcode方法,由于hash值不同,所以没有调用equals方法。
然后我们添加两遍同一个元素:
package info.dyndns.oszc;
import java.util.HashSet;
public class HashSetTest {
public void test(){
HashSet<Person> hs = new HashSet<Person>();
hs.add(new Person("zs", 11));
hs.add(new Person("zs", 11));
Utils.printElements(hs);
}
public static void main(String[] args) {
HashSetTest hst = new HashSetTest();
hst.test();
}
}
output:
调用hashCode方法,hash为:389799
调用hashCode方法,hash为:389799
调用equals方法
zs..11
可以看出当hash值相同时,equals方法会被调用,当他们都相同,则hashset判断两个元素完全一致,所以后一个元素未能加入到hashset集合中。
所以我们在自定义类要添加到hashset中时候,务必重写以上两个方法,来保证hashset添加元素的唯一性。