详解Object中的equals方法和hashcode方法

参考资料:重写实体类的equals 和hashCode 方法!

object的equals方法重写过程解释

因为object的equals方法如下

    public boolean equals(Object obj) {
        return (this == obj);
    }

Object中提供的equals方法是默认比较的是两个对象的引用地址(底层也是用的“==”)
所以自定义实体类需要重写equals方法,具体过程如下:(重写equals方法可以改写比较规则)

  @Override
    public boolean equals(Object obj) {
        //6、增加一个判断,传递的参数obj如果是this本身,直接返回true。提高效率
        if (obj == this) {
            return true;
        }

        //5、如果传进来的是null(引用数据类型的默认值,null 表示缺乏标识,表示变量不指向任何对象。),直接返回false,提高效率
        if (obj == null) {
            return false;
        }
        //3、防止传进来的是集合而不是该类型的对象,所以需要判断: obj 是Student的本类或者子类的实体对象时才执行
        if (obj instanceof Student) {
            //1、需要注意,这里有个隐形的多态。多态的弊端是:不能使用子类中特有的内容(属性和方法)。所以需要进行向下转型
            Student s = (Student) obj;
            //2、拿到该类对象,进行比较各属性
            boolean b = this.age == age && this.name.equals(s.name);
            return b;
        }
        //4、如果是集合,则返回false
        return false;

    }

用快捷键生成的如下:

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        //getClass() != o.getClass() 使用反射技术,判断o是不是Student类型。
        if (o == null || getClass() != o.getClass()) return false;
        Student student = (Student) o;
        return Objects.equals(name, student.name) && Objects.equals(age, student.age);
    }

Objects的equals方法的详解

JDK7添加了一个Objects工具类,它提供了一些方法来操作对象,它由一些静态的实用方法组成,这些方法是null-save(空指针安全的)或null-tolerant(容忍空指针的),用于计算对象的hashcode,返回对象的字符串表示形式,比较两个对象。

Objects的equals方法介绍:如果两个对象相等就返回true,如果一个为null就返回false,如果两个都是null则返回true。

    public static boolean equals(Object a, Object b) {
        return (a == b) || (a != null && a.equals(b));
    }
     ```
     
     System.out.println(null==null);//true

哈希表的操作详解

我们知道哈希表采用的是数组+链表的结构,每个数组上挂载着链表,链表的节点用来存储对象信息,而对象落到数组的位置由 hashcode()。所以当我们调用 HashSet 的 add(Object o) 方法时,首先会根据o.hashCode()的返回值定位到相应的数组位置,如果该数组位置上没有结点,则将 o 放到这里,如果已经有结点了, 则把 o 挂到链表末端。同理,当调用 contains(Object o) 时,Java 会通过 hashCode()的返回值定位到相应的数组位置,然后再在对应的链表中的结点依次调用 equals() 方法来判断结点中的对象是否是你想要的对象。

equals 方法的通用约定

在 Object 中有如下规范: equals 方法实现了一个等价关系(equivalence relation)。它有以下这些属性:
自反性:对于任何非空引用 x,x.equals(x) 必须返回 true
对称性:对于任何非空引用 x 和 y,如果且仅当 y.equals(x) 返回 true 时 x.equals(y) 必须返回 true
传递性:对于任何非空引用 x、y、z,如果 x.equals(y) 返回 true,y.equals(z) 返回 true,则 x.equals(z) 必须返回 true
一致性:对于任何非空引用 x 和 y,如果在 equals 比较中使用的信息没有修改,则 x.equals(y) 的多次调用必须始终返回 true 或始终返回 false
非空性:对于任何非空引用 x,x.equals(null) 必须返回 false

    // 使用 @Override 标记,这样就可以避免上面的错误
    @Override
    public boolean equals(Object o) {undefined
        // 1、判断是否等于自身
        if (this == o) return true;
        // 2、判断 o 对象是否为空 或者类型是否为 Article 
        if (o == null || !(o instanceof  Article)) return false;
        // 3、参数类型转换
        Article article = (Article) o;
        // 4、判断两个对象的 url 是否相等
        return article.url.equals(url);
    }

以上的第二步可以写成getClass(),参考资料:java中instanceof和getClass()的作用

哈希冲突

String 重写了 hashcode方法,保证内容不一样时它的哈希值就不一样。
hashcode方法哈希冲突( String name ,int age ; 张三 (哈希值是:21) , 30;李四(哈希值是:30),21 )

解决办法

扩大了31倍。(数字太小,不行。数字太大,可能会溢出,所以取一个合适的数。)

为什么用IDEA写hashcode方法,有31这个数字?
1、选择系数的时候要选择尽量大的系数。因为如果计算出来的hash地址越大,所谓的“冲突”就越少,查找起来效率也会提高。(减少冲突)
2、并且31只占用5bits,相乘造成数据溢出的概率较小。
3、31可以由i*31==(i<<5)-1来表示,现在很多虚拟机里面都有做相关优化。(提高算法效率)
4、31是一个素数,素数作用就是如果我用一个数字来乘以这个素数,那么最终出来的结果只能被素数本身和被乘数还有1来整除!(减少冲突)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值