关于java:java中equalshashcode和的区别

1、==

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

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

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

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

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

对象是放在堆中的,栈中寄存的是对象的援用(地址)。由此可见’==’是对栈中的值进行比拟的。如果要比拟堆中对象的内容是否雷同,那么就要重写equals办法了。

例:

public static void main(String[] args) {  
  
        int int1 = 12;  
        int int2 = 12;  
        Integer Integer1 = new Integer(12);  
        Integer Integer2 = new Integer(12);  
        Integer Integer3 = new Integer(127);  
  
        Integer a1 = 127;  
        Integer b1 = 127;  
  
        Integer a = 128;  
        Integer b = 128;  
  
        String s1 = "str";  
        String s2 = "str";  
        String str1 = new String("str");  
        String str2 = new String("str");  
  
        System.out.println("int1==int2:" + (int1 == int2));  
        System.out.println("int1==Integer1:" + (int1 == Integer1));  
        System.out.println("Integer1==Integer2:" + (Integer1 == Integer2));  
        System.out.println("Integer3==b1:" + (Integer3 == b1));  
        System.out.println("a1==b1:" + (a1 == b1));  
        System.out.println("a==b:" + (a == b));  
          
  
        System.out.println("s1==s2:" + (s1 == s2));  
        System.out.println("s1==str1:" + (s1 == str1));  
        System.out.println("str1==str2:" + (str1 == str2));  
  
    } /./*欢送退出java交换Q君样:909038429一起吹水聊天 

输入后果:

int1==int2:true
int1==Integer1:true //Integer会主动拆箱为int,所以为true
Integer1==Integer2:false//不同对象,在内存寄存地址不同,所以为false
Integer3==b1:false//Integer3指向new的对象地址,b1指向缓存中127地址,地址不同,所以为false

a1==b1:true
a==b:false

s1==s2:true
s1==str1:false
str1==str2:false

Integer b1 = 127;java在编译的时候,被翻译成-> Integer b1 = Integer.valueOf(127);

public static Integer valueOf(int i) {  
        assert IntegerCache.high >= 127;  
        if (i >= IntegerCache.low && i <= IntegerCache.high)  
            return IntegerCache.cache[i + (-IntegerCache.low)];  
        return new Integer(i);  
    }  

看一下源码大家都会明确,对于-128到127之间的数,会进行缓存,Integer b1 = 127时,会将127进行缓存,下次再写Integer i6 = 127时,就会间接从缓存中取,就不会new了。所以a1==b1:true a==b:false

2、equals

1、默认状况(没有笼罩equals办法)下equals办法都是调用Object类的equals办法,而Object的equals办法次要用于判断对象的内存地址援用是不是同一个地址(是不是同一个对象)。上面是Object类中equals办法:

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

定义的equals与==是等效的

2 、要是类中笼罩了equals办法,那么就要依据具体的代码来确定equals办法的作用了,笼罩后个别都是通过对象的内容是否相等来判断对象是否相等。上面是String类对equals进行了重写:

public boolean equals(Object anObject) {  
    if (this == anObject) {  
        return true;  
    }  
    if (anObject instanceof String) {  
        String anotherString = (String)anObject;  
        int n = count;  
        if (n == anotherString.count) {  
        char v1[] = value;  
        char v2[] = anotherString.value;  
        int i = offset;  
        int j = anotherString.offset;  
        while (n-- != 0) {  
            if (v1[i++] != v2[j++])  
            return false;  
        }  
        return true;  
        }  
    }  /./*欢送退出java交换Q君样:909038429一起吹水聊天
    return false;  
    }  

即String中equals办法判断相等的步骤是:

1.若A==B 即是同一个String对象 返回true

2.若比照对象是String类型则持续,否则返回false

3.判断A、B长度是否一样,不一样的话返回false

4。一一字符比拟,若有不相等字符,返回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办法的窍门:
1.应用==符号查看“参数是否为这个对象的援用”。如果是,则返回true。这只不过是一种性能优化,如果比拟操作有可能很低廉,就值得这么做。
2.应用instanceof操作符查看“参数是否为正确的类型”。如果不是,则返回false。一般来说,所谓“正确的类型”是指equals办法所在的那个类。
3.把参数转换成正确的类型。因为转换之前进行过instanceof测试,所以确保会胜利。
4.对于该类中的每个“要害”域,查看参数中的域是否与该对象中对应的域相匹配。如果这些测试全副胜利,则返回true;否则返回false。
5.当编写实现了equals办法之后,查看“对称性”、“传递性”、“一致性”。

3、hashCode

hashCode()办法返回的就是一个数值,从办法的名称上就能够看出,其目标是生成一个hash码。hash码的主要用途就是在对对象进行散列的时候作为key输出,据此很容易推断出,咱们须要每个对象的hash码尽可能不同,这样能力保障散列的存取性能。事实上,Object类提供的默认实现的确保障每个对象的hash码不同(在对象的内存地址根底上通过特定算法返回一个hash码)。Java采纳了哈希表的原理。哈希(Hash)实际上是集体名,因为他提出一哈希算法的概念,所以就以他的名字命名了。 哈希算法也称为散列算法,是将数据依特定算法间接指定到一个地址上。初学者能够这样了解,hashCode办法实际上返回的就是对象存储的物理地址(理论可能并不是)。

散列函数,散列算法,哈希函数。
是一种从任何一种数据中创立小的数字“指纹”的办法。
散列函数将任意长度的二进制值映射为较短的固定长度的二进制值,这个小的二进制值称为哈希值。
好的散列函数在输出域中很少呈现散列抵触。

所有散列函数都有如下一个根本个性:
1:如果a=b,则h(a) = h(b)。
2:如果a!=b,则h(a)与h(b)可能失去雷同的散列值。

Object 的hashCode办法:返回一个int类型

public native int hashCode();  

3.1 hashCode的作用

想要明确,必须要先晓得Java中的汇合。  
总的来说,Java中的汇合(Collection)有两类,一类是List,再有一类是Set。前者汇合内的元素是有序的,元素能够反复;后者元素无序,但元素不可反复。

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

这就是Object.equals办法了。然而,如果每减少一个元素就查看一次,那么当元素很多时,后增加到汇合中的元素比拟的次数就十分多了。也就是说,如果汇合中当初曾经有1000个元素,那么第1001个元素退出汇合时,它就要调用1000次equals办法。这显然会大大降低效率。
于是,Java采纳了哈希表的原理。

这样一来,当汇合要增加新的元素时,

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

如果这个地位上没有元素,它就能够间接存储在这个地位上,不必再进行任何比拟了;

如果这个地位上曾经有元素了,就调用它的equals办法与新元素进行比拟,雷同的话就不存,不雷同就散列其它的地址。所以这里存在一个抵触解决的问题。这样一来理论调用equals办法的次数就大大降低了,简直只须要一两次。

4、eqauls办法和hashCode办法关系

Java对于eqauls办法和hashCode办法是这样规定的:

(1)同一对象上屡次调用hashCode()办法,总是返回雷同的整型值。

(2)如果a.equals(b),则肯定有a.hashCode() 肯定等于 b.hashCode()。

(3)如果!a.equals(b),则a.hashCode() 不肯定等于 b.hashCode()。此时如果a.hashCode() 总是不等于 b.hashCode(),会进步hashtables的性能。

(4)a.hashCode()==b.hashCode() 则 a.equals(b)可真可假

(5)a.hashCode()!= b.hashCode() 则 a.equals(b)为假。

下面论断简记:

1、如果两个对象equals,Java运行时环境会认为他们的hashcode肯定相等。
2、如果两个对象不equals,他们的hashcode有可能相等。
3、如果两个对象hashcode相等,他们不肯定equals。
4、如果两个对象hashcode不相等,他们肯定不equals。

对于这两个办法的重要标准:

标准1:若重写equals(Object obj)办法,有必要重写hashcode()办法,确保通过equals(Object obj)办法判断后果为true的两个对象具备相等的hashcode()返回值。说得简略点就是:“如果两个对象雷同,那么他们的hashcode应该相等”。不过请留神:这个只是标准,如果你非要写一个类让equals(Object obj)返回true而hashcode()返回两个不相等的值,编译和运行都是不会报错的。不过这样违反了Java标准,程序也就埋下了BUG。

标准2:如果equals(Object obj)返回false,即两个对象“不雷同”,并不要求对这两个对象调用hashcode()办法失去两个不雷同的数。说的简略点就是:“如果两个对象不雷同,他们的hashcode可能雷同”。

5、为什么笼罩equals时总要笼罩hashCode
一个很常见的谬误本源在于没有笼罩hashCode办法。在每个笼罩了equals办法的类中,也必须笼罩hashCode办法。如果不这样做的话,就会违反Object.hashCode的通用约定,从而导致该类无奈联合所有基于散列的汇合一起失常运作,这样的汇合包含HashMap、HashSet和Hashtable。

1.在应用程序的执行期间,只有对象的equals办法的比拟操作所用到的信息没有被批改,那么对这同一个对象调用屡次,hashCode办法都必须始终如一地返回同一个整数。在同一个应用程序的屡次执行过程中,每次执行所返回的整数能够不统一。

2.如果两个对象依据equals()办法比拟是相等的,那么调用这两个对象中任意一个对象的hashCode办法都必须产生同样的整数后果。

3.如果两个对象依据equals()办法比拟是不相等的,那么调用这两个对象中任意一个对象的hashCode办法,则不肯定要产生雷同的整数后果。然而程序员应该晓得,给不相等的对象产生截然不同的整数后果,有可能进步散列表的性能。

6、总结:
1、equals办法用于比拟对象的内容是否相等(笼罩当前)

2、hashcode办法只有在汇合中用到

3、当笼罩了equals办法时,比拟对象是否相等将通过笼罩后的equals办法进行比拟(判断对象的内容是否相等)。

4、将对象放入到汇合中时,首先判断要放入对象的hashcode值与汇合中的任意一个元素的hashcode值是否相等,如果不相等间接将该对象放入汇合中。如果hashcode值相等,而后再通过equals办法判断要放入对象与汇合中的任意一个对象是否相等,如果equals判断不相等,间接将该元素放入到汇合中,否则不放入。

最新2020整顿收集的一些高频面试题(都整顿成文档),有很多干货,蕴含mysql,netty,spring,线程,spring cloud、jvm、源码、算法等具体解说,也有具体的学习规划图,面试题整顿等,须要获取这些内容的敌人请加Q君样:909038429
/./*欢送退出java交换Q君样:909038429一起吹水聊天

评论

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

这个站点使用 Akismet 来减少垃圾评论。了解你的评论数据如何被处理