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

  • 相关阅读:
    加深对C#数据类型的认识
    Spring------关于代理
    Java数组
    C#小型资源管理器
    面向对象七大原则
    关于C#换肤IrisSkin
    非泛型集合
    经理评价系统总结
    深入.NET框架
    航班系统总结
  • 原文地址:https://www.cnblogs.com/javawork/p/7228348.html
Copyright © 2020-2023  润新知