• java基础 equals与hashCode


    Java中equals相关

    equals()与==的关系

    ==:它是一个操作符,作用是判断两个对象的地址是否相等

    基础类型比较的是值,引用类型比较的是内存地址

    equals()

    • 类未覆盖equals()方法,则调用Object类提供的equals(),等价于通过“==”进行比较
    • 类覆盖equals()方法,为了比较两者内容是否相等,如相等则返回true

    equals()即使被覆盖,通常第一步也是利用"=="进行判断,若为false,再根据不同类型对值进行判断

    举例

     public static void main(String[] args) {
           String var1 = new String("asd");
           String var2 = new String("asd");
           String var3 = "asd";
           String var4 = "asd";
            System.out.println(var1.equals(var2));
            System.out.println(var1 == var2);
            System.out.println(var1 == var3);
            System.out.println(var3 == var4);
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    输出
    在这里插入图片描述
    说明:

    从上面,可以看到String类重写了equals(),因为它可以判断字符串内容是否相等返回true或false。
    同时,可以注意到,String类有两种实例化方式,及直接赋值和new,new方法是直接在堆中创建一个对象,而String的赋值先检查常量池中是否有相同的字符串常量,如果有则让String变量指向此字符串常量地址,否则在常量池中创建一个字符串常量。
    所以,看到String直接赋值的变量比较地址时是返回true的

    equals()和hashCode()

    首先,我们要记住,不管是否运用到Key-Value集合中,重写equals()一定要重写hashCode(),因为这是一个设计规范,你永远不知道这个类型未来是否会运用到Key-Value中。记住之后,下面我们来详细讲解原理上的原因

    hashCode()介绍

    1. hashCode()的作用是获取哈希码(散列码),返回类型是一个整数。哈希码是用来获取对象在哈希表的索引位置的(如,在hashMap中就是利用哈希码与哈希表(数组结构)的长度的取模运算得到索引位置)。
    2. hashCode()是定义在Object.java中,及所有类都包含它。它主要在类充当散列表类(hashMap,hashtable)中Key值或散列表类(hashSet)中元素时,起到判重的作用。

    hashCode()的意义

    比如在HashSet集合中,由于其不可重复特性,在检测重复时,利用率hashCode
    当你把对象加入 HashSet 时,HashSet 会先计算对象的 hashcode 值来判断对象加入的位置,同时也会与该位置其他已经加入的对象的 hashcode 值作比较,如果没有相符的 hashcode,HashSet 会假设对象没有重复出现。但是如果发现有相同 hashcode 值的对象,这时会调用 加入对象所属类中的equals()方法来检查加入对象和集合中 hashcode 相等的对象是否真的相同。如果两者相同,HashSet 就不会让其加入操作成功。这样可以在equals()之前先判断一次,及筛选一次,减少equals()b比较次数,提高效率。
    HashSet是基于HashMap实现的其判重操作也是调用的HashMap中put()

    hashCode()和equals()的关系

    从逻辑上讲,相等对象的哈希值一定相等,同时由于不相等对象的哈希值也可能相同及哈希碰撞。所以我们可以得到一个一般规律:当对象,equals()相等时,hashCode()返回值一定相等,equals()不等时,hashCode()不一定不等。

    所以,在类被应用到散列表类型时(HashMap,Hashtable,HashSet),我们希望可以通过相等的对象获取到对于的value和相等的对象在HashSet集合中不重复,及equals()相等的对象,在散列表中只存在一个。
    如果重写equals()不重写hashCode():默认会调用Object.java中的本地方法hashCode(),这会导致,在equals()判断相等的两个对象,哈希码不同,从而与我们希望的逻辑结果不同。

    举例

    创建一个User类,分两次实验

    1. 重写hashCode()
    2. 不重写hashCode()
    public class User {
        private String name;
        private int  hash;
        public User(String name) {
            this.name = name;
        }
        @Override
        public boolean equals(Object obj) {
            // return super.equals(obj);
            // if (obj.getClass().equals(User.class)) {}
            if (obj instanceof User) {
                User c = (User) obj;
                return name == c.name;
            }
            return false;
        }
        @Override
        public int hashCode(){
            return Objects.hash(name);
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22

    执行的主方法类

    public class HashMapDemo {
        public static void main(String[] args) {
    
            User user1 = new User("李一");
            User user2 = new User("李一");
    
            System.out.println("user1.hashCode())>>>"+ user1.hashCode());
            System.out.println("user2.hashCode())>>>"+ user2.hashCode());
            HashMap<User ,String>map = new HashMap<>();
            map.put(user1,"李一");
    
            System.out.println("Key>>user1  "+map.get(user1));
            System.out.println("Key>>user2  "+map.get(user2));
    
    
    
        }
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    运行结果

    第一次:不重写hashCode()
    在这里插入图片描述
    第二次:重写hashCode()
    在这里插入图片描述
    说明:

    • 重写的hashCode()中,调用了Objects类中的hash(value),其功能是根据参数通过某种哈希函数产生哈希码,这里是根据name产生哈希码

    分析

    可以发现,两次执行的结果中,前者未重写hashCode(),对象相等,但是哈希值不相等,导致在HashMap中相当于两个不同的key,无法通过相等对象获取value。而重写后hashCode()则实现了期望。

    总结

    1. equals()与操作符==的关系
      简单的说
      • equals()经过重写后要达到判断值相等的功能
      • 操作符==:是判断引用类型地址的是否相等以及基础类型(byte,int,short,long,char,double,float,char,boolean)的值是否相等的
    2. equals()与hashCode的关系
      • hashCode()返回整数,及哈希值,它是定义在Object.java中的
      • 重写equals()必要重写hashCode(),因为在类被用于散列表中时,不重写hashCode()会导致equals()相等的对象在散列表中被认为是不同的。

    我要在最后重复一遍的是:有人可能会认为只要不将该类用在散列表类型中就不需要在重写equals()情况下重写hashCode(),当然从执行上来说是这样没错,但是为了代码的可扩展性安全性来讲,是有问题的,因为你无法预料到未来是否会将其用到散列表中。所以在日常编程中,严格遵守设计规范是有必要的。

  • 相关阅读:
    CDA Level1——1.数据分析的基本概念
    ECharts-数据可视化复习(58th)
    c++STL容器(看这一篇就够)
    隐藏的增长动力:中国工业的售后服务
    【组件传参】返回e和传入的参数 - uniapp中this.$emit回传多个值 - uniapp组件中带事件参数event和多个参数
    Chapter5.5:频率响应法
    .NET 6当中的Web API版本控制
    JUnit进行单元测试
    每日复盘-202406019
    自媒体账号的流量推荐减少了很多?
  • 原文地址:https://blog.csdn.net/qq_45515347/article/details/126613842