之前在《java常用对象API之集合框架》这篇文章中已经将所有集合框架做了一个总体的大纲陈列,并阐述了所有Collection接口下的子接口和类的作用解释,那么接下来的文章智言还是想把里面的一些比较难的接口和类进行一个剖析,让各位新加入学习java的朋友可以得以启发,并激情的继续往java这条路上走的更远。
HashSet是Set接口下的一个类,它的内部数据结构是哈希表 ,是不同步的。
既然HashSet是不同步的,那么如何来保证该集合的元素唯一性呢?
是通过对象的hashCode和equals方法来完成对象唯一性的。
如果对象的hashCode值不同,那么不用判断equals方法,就直接存储到哈希表中。
如果对象的hashCode值相同,那么要再次判断对象的equals方法是否为true,如果为true,视为相同元素,不存。如果为false,那么视为不同元素,就进行存储。
例如:
1.首先建立Person类
public class Person{
private String name;
private int age;
public Person(String name, int age){
super();
this.name=name;
this.age=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;
}
}
2.然后建立主函数HashSetDemo类
public class JavaDemo{
public static void main(String[] args){
HashSet hs = new HashSet();
hs.add(new Person(“张三”,21));
hs.add(new Person(“李四”,23));
hs.add(new Person(“王五”,22));
hs.add(new Person(“麻子”,24));
Iterator it = hs.iterator(); //创建迭代器
while(it.hasNext()){
Person p = (Person)it.next(); //由于it的next()方法是继承的Object类,所以这里需要强制转换成Person类型
System.out.println(p.getName()+”…”+p.getAge());
}
}
}
3.显示结果:
张三….21
王五….23
麻子….24
李四….22
上面的例子只是指出了HashSet的具体作用展现,但是它是如果在底层进行工作的呢?这个时候就需要讲到HashCode和equals这个两个方法的作用。
那么我们还是用例子来简单讲解一下,首先我们在上面例子中主函数HashSetDemo类里再加入一段代码
hs.add(new Person(“李四”,22));
即主函数HashSetDemo类中有两个一模一样的hs.add(new Person(“李四”,22));对象,那么很明显,最后的显示结果肯定会是:
张三….21
王五….23
麻子….24
李四….22
李四….22
答案是肯定的,因为Person类默认继承了Object类,所以实现了Object类里的hashCode方法,这样就没有体现出HashSet中hashCode和equals这两个方法的一个价值,那么我们来慢慢讲解一下。
其实HashSet这个类就像最上面讲的如果对象的hashCode值不同,那么不用判断equals方法,就直接存储到哈希表中。如果对象的hashCode值相同,那么要再次判断对象的equals方法是否为true,如果为true,视为相同元素,不存。如果为false,那么视为不同元素,就进行存储。
4.那么这个时候我们可以重写hashCode和equals这两个方法来验证HashSet的底层运行流程。
我们首先在Person类里添加hashCode和equals这两个方法:
public int hashCode(){
System.out.println(this+”…hashCode”);
return name.hashCode()+age;
}
public boolean equals(Object obj){
System.out.println(this+”…equals…”+obj);
Person p = (Person)obj;
return this.name.equals(p.name)&&this.age==p.age;
}
另外为了看的更明白一点,我把toString方法也重写一样:
public String toString(){
return name+”:”+age;
}
这个时候再运行主函数会显示:
张三:21…hashCode
李四:22…hashCode
王五:23…hashCode
麻子:24…hashCode
李四:22…hashCode
李四:22…equals…李四:22
张三….21
李四….22
王五….23
麻子….24
那么上面红色显示的就是使用了自定义hashCode和equals后具备了唯一性的HashSet表现形式
记住:如果元素要存储到HashSet集合中,必须覆盖hashCode方法和equals方法。一般情况下,如果定义的类会产生很多对象,比如人,学生,书,通常都需要覆盖equals,hashCode方法。建立对象判断是否相同的依据。