• 从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

  • 相关阅读:
    Java实现各种内部排序算法
    Java实现堆排序(大根堆)
    Java对象的序列化和反序列化
    Java实现链式存储的二叉查找树(递归方法)
    337. House Robber III(包含I和II)
    318. Maximum Product of Word Lengths
    114. Flatten Binary Tree to Linked List
    106. Construct Binary Tree from Inorder and Postorder Traversal
    105. Construct Binary Tree from Preorder and Inorder Traversal
    96. Unique Binary Search Trees(I 和 II)
  • 原文地址:https://www.cnblogs.com/javawork/p/7228348.html
Copyright © 2020-2023  润新知