一个关于HashSet去重的实例
在下面的代码中,我们使用HashSet来添加两个对象,众所周知HashSet存储数据的特点是:无序,不重复。但是如何鉴定两个对象之间是否重复呢?
下面是一个简单的案例,将Student对象添加到HashSet中,但是要求name和age相同的对象我们认为是重复的,不能添加到集合中。
public class Student {
String name; int age;
public Student(String name,int age){ this.name = name; this.age = age; } @Override
//重写equals方法,我们认为Student对象,如果姓名和年龄一样就认为是同一个对象。 public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; Student student = (Student) o; if (age != student.age) return false; return name.equals(student.name); } }
上面是一个很简单的对象,将对象加入HashSet中,查看结果
public class TestMain { public static void main(String[] args) { Set<Student> students = new HashSet<Student>(); Student s1 = new Student("zhangsan",12); Student s2 = new Student("zhangsan",12); students.add(s1); students.add(s2); //查看set集合中的个数 System.out.println(students.size()); } }
结果集合的个数为 2 。其主要原因是因为忽视了hashCode
hashCode的作用
hashCode重要吗?为什么我们很少关注它?其实对于List集合、数组而言,他就是一个累赘,但是对于HashMap、HashSet、HashTable而言,它变得异常重要。
HashMap、HashSet、HashTable都是使用哈希表类存储数据的,hashCode方法是为了提高哈希表性能的解决方案。
当我们向一个集合中添加某个元素,集合会首先调用hashCode方法,这样就可以直接定位它所存储的位置,若该处没有其他元素,则直接保存。若该处已经有元素存在,就调用equals方法来匹配这两个元素是否相同,相同则不存,不同则散列到其他位置。这样处理,当我们存入大量元素时就可以大大减少调用equals()方法的次数,极大地提高了效率。
hashCode与equals
hashCode的实现总是伴随着equals,他们是紧密配合的,你要是自己设计了其中一个,就要设计另外一个。
至于两者之间的关联关系,我们只需要记住如下即可:
1.如果x.equals(y)返回“true”,那么x和y的hashCode()必须相等。
2. 如果x.equals(y)返回“false”,那么x和y的hashCode()有可能相等,也有可能不等。
理清了上面的关系我们就知道他们两者是如何配合起来工作的。先看下图:
整个处理流程是:
1、判断两个对象的hashcode是否相等,若不等,则认为两个对象不等,完毕,若相等,则比较equals。
2、若两个对象的equals不等,则可以认为两个对象不等,否则认为他们相等。
修改案例并测试
public class Student { String name; int age; public Student(String name,int age){ this.name = name; this.age = age; } @Override //重写equals方法,我们认为Student对象,如果姓名和年龄一样就认为是同一个对象。 public boolean equals(Object o) { System.out.println("调用了equals方法"); if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; Student student = (Student) o; if (age != student.age) return false; return name.equals(student.name); } @Override //添加hashCode方法,使对象name,age相同时,hashCode也保持一致 public int hashCode() { System.out.println("调用了hashCode方法"); int result = name.hashCode(); result = 31 * result + age; return result; } }
运行结果:
调用了hashCode方法
调用了hashCode方法
调用了equals方法
1
参考资料: