专栏首页Android开发实战java中equals,hashcode和==的区别

java中equals,hashcode和==的区别

java中equals,hashcode和==的区别 相信很多人都很清楚

  1. ==运算符是判断两个对象是不是同一个对象,即他们的地址是否相等
  2. object类中equals与==是等效的
  3. 覆写equals更多的是追求两个对象在逻辑上的相等,你可以说是值相等,也可说是内容相等。(覆盖以后,覆盖equals时总要覆盖hashCode )
  4. hashCode用于返回对象的hash值,主要用于查找的快捷性,因为hashCode也是在Object对象中就有的,所以所有Java对象都有hashCode,在HashTable和HashMap这一类的散列结构中,都是通过hashCode来查找在散列表中的位置的。

知识拓展图(总结拓展如下):

一. Java == 运算符

java中的数据类型,可分为两类:

1.基本数据类型,也称原始数据类型

byte,short,char,int,long,float,double,boolean 他们之间的比较,应用双等号(==),比较的是他们的值。

2.引用类型(类、接口、数组)

当他们用(==)进行比较的时候,比较的是他们在内存中的存放地址,所以,除非是同一个new出来的对象,他们的比较后的结果为true,否则比较后结果为false。

对象是放在堆中的,栈中存放的是对象的引用(地址)。由此可见'=='是对栈中的值进行比较的。如果要比较堆中对象的内容是否相同,那么就要重写equals方法了。

二. Java里面有==运算符了,为什么还需要equals

equals()的作用是用来判断两个对象是否相等,在Object里面的定义是:

//equals与==是等效的public boolean equals(Object obj) {        return (this == obj);    }

这说明在我们实现自己的equals方法之前,equals等价于==,而==运算符是判断两个对象是不是同一个对象,即他们的地址是否相等。而覆写equals更多的是追求两个对象在逻辑上的相等,你可以说是值相等,也可说是内容相等。 String.java中对equals方法的重写

   public boolean equals(Object anObject) {        if (this == anObject) {            return true;       }        if (anObject instanceof String) {
           String anotherString = (String)anObject;            int n = value.length;            if (n == anotherString.value.length) {                char v1[] = value;                char v2[] = anotherString.value;                int i = 0;                while (n-- != 0) {                    if (v1[i] != v2[i])                        return false;                    i++;               }                return true;           }       }        return false;    }

这里对equals重新需要注意五点:

  1. 自反性:对任意引用值X,x.equals(x)的返回值一定为true.
  2. 对称性:对于任何引用值x,y,当且仅当y.equals(x)返回值为true时,x.equals(y)的返回值一定为true;
  3. 传递性:如果x.equals(y)=true, y.equals(z)=true,则x.equals(z)=true
  4. 一致性:如果参与比较的对象没任何改变,则对象比较的结果也不应该有任何改变
  5. 非空性:任何非空的引用值X,x.equals(null)的返回值一定为false

在以下几种条件中,不覆写equals就能达到目的:

  • 类的每个实例本质上是唯一的:强调活动实体的而不关心值得,比如Thread,我们在乎的是哪一个线程,这时候用equals就可以比较了。
  • 不关心类是否提供了逻辑相等的测试功能:有的类的使用者不会用到它的比较值得功能,比如Random类,基本没人会去比较两个随机值吧
  • 超类已经覆盖了equals,子类也只需要用到超类的行为:比如AbstractMap里已经覆写了equals,那么继承的子类行为上也就需要这个功能,那也不需要再实现了。
  • 类是私有的或者包级私有的,那也用不到equals方法:这时候需要覆写equals方法来禁用它:

@Override public boolean equals(Object obj) { throw new AssertionError();}

三. hashCode,有什么用?

hashCode()方法返回的就是一个数值,从方法的名称上就可以看出,其目的是生成一个hash码。hash码的主要用途就是在对对象进行散列的时候作为key输入,据此很容易推断出,我们需要每个对象的hash码尽可能不同,这样才能保证散列的存取性能。事实上,Object类提供的默认实现确实保证每个对象的hash码不同(在对象的内存地址基础上经过特定算法返回一个hash码)。Java采用了哈希表的原理。哈希(Hash)实际上是个人名,由于他提出一哈希算法的概念,所以就以他的名字命名了。 哈希算法也称为散列算法,是将数据依特定算法直接指定到一个地址上。初学者可以这样理解,hashCode方法实际上返回的就是对象存储的物理地址(实际可能并不是)。

3.1 hashCode的作用

想要明白,必须要先知道Java中的集合。   总的来说,Java中的集合(Collection)有两类,一类是List,再有一类是Set。前者集合内的元素是有序的,元素可以重复;后者元素无序,但元素不可重复。

那么这里就有一个比较严重的问题了:要想保证元素不重复,可两个元素是否重复应该依据什么来判断呢?

这就是Object.equals方法了。但是,如果每增加一个元素就检查一次,那么当元素很多时,后添加到集合中的元素比较的次数就非常多了。也就是说,如果集合中现在已经有1000个元素,那么第1001个元素加入集合时,它就要调用1000次equals方法。这显然会大大降低效率。 于是,Java采用了哈希表的原理。

这样一来,当集合要添加新的元素时,

先调用这个元素的hashCode方法,就一下子能定位到它应该放置的物理位置上。

如果这个位置上没有元素,它就可以直接存储在这个位置上,不用再进行任何比较了;

如果这个位置上已经有元素了,就调用它的equals方法与新元素进行比较,相同的话就不存,不相同就散列其它的地址。所以这里存在一个冲突解决的问题。这样一来实际调用equals方法的次数就大大降低了,几乎只需要一两次。 参考网站内容如下: https://juejin.im/post/5a4379d4f265da432003874c equals与hashCode问题记录 https://www.cnblogs.com/kexianting/p/8508207.html java中equals,hashcode和==的区别 https://www.cnblogs.com/dolphin0520/p/3613043.html JVM的内存区域划分 https://www.jianshu.com/p/589d58033841 集合框架 Collection、Map https://www.jianshu.com/p/0ce2279c5691 自动装箱与拆箱的实现原理

-----------------------------------------------------------

本文分享自微信公众号 - 编码恒字诀(gh_db8538619cdd)

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2019-02-12

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • Dalvik,ART与ODEX简析

    如果你有这样的问题: 1.Dalvik和ART的区别 2.DEX在Dalvik转化为ODEX和ART中转化为ODEX的过程有上面区别 3.multidex在da...

    Anymarvel
  • 深入理解Java泛型(二)通配符与嵌套

    从上面代码我们知道,就算容器中的类型之间存在继承关系,但是Plate和Plate两个容器之间是不存在继承关系的。在这种情况下,Java就设计成Plate<? e...

    Anymarvel
  • 深入理解Java泛型(一.泛型的作用与定义)

    泛型使编译器可以在编译期间对类型进行检查以提高类型安全,减少运行时由于对象类型不匹配引发的异常。

    Anymarvel
  • Effective Java(二)

    尽管 Object 是一个具体类,但设计它主要是为了扩展。它所有的非 final 方法(equals、hashCode、toString、clone和final...

    Remember_Ray
  • 用了这么久的equals,你知道还要遵守约定么

    重写equals 方法看起来很简单,但是还会有多种方式导致出错,后果可能是严重的。最简单,最容易避免出错的方式是 避免重写equals方法 ,采用这种方式的每个...

    cxuan
  • Java基础系列(十七):Object类(上)

    在Java中,只有基本数据类型不是对象,比如,数值,布尔和字符类型的值都不是对象。而其余的数据类型都是继承自一个名为Object的类,这个类是所有类的始祖,每个...

    山禾说
  • Effective.Java 读书笔记(8)关于equals方法

    重写equals看上去十分简单对吧,但是我觉得很多时候重写equals可能会招致一些问题,这些问题有时可能会特别严重,当然了不重写不就完事了吗?但是这只适用于那...

    Mezereon
  • ​第3章 对于所有对象都通用的方法

    现在技术圈特别浮躁,也很容易被感染,看了很多文章很多博客,最后发现自己依然不懂,再加上每天信息爆炸,就特别容易浮躁

    程序亦非猿
  • equals方法的理解

    通常在面试中会被问到equals方法和==的区别,以及有没有重写过equals方法,以及重写equals方法的约定是什么? 下面简单的介绍一下我的理解: 首...

    聚沙成塔
  • JAVA-为什么equals和hashcode在重写时要保持一致

    在java中equals方法是写在Object类中的,这个方法是用来检测一个对象是否等于另一个对象。在Object类中这个方法判断两个对象是否具有相同的引用。

    用户7886150

扫码关注云+社区

领取腾讯云代金券