从Hashset 添加对象去重问题看 hashCode()的重要性

一个关于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()有可能相等,也有可能不等。

  理清了上面的关系我们就知道他们两者是如何配合起来工作的。先看下图:

            2014040701_thumb2

    整个处理流程是:

      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

 

参考资料:

Java提高篇(二六)——hashCode

 

posted @ 2017-07-24 15:40  智商输给猪  阅读(415)  评论(1编辑  收藏  举报