==、equals()、hashcode()对比

结论:

1.     对于基本数据类型,==比较的是值,equals方法不能使用

2.     对于String和包装类,==比较的是地址,equals方法比较的是值

3.     对于继承Object的类,==比较的是地址,equals比较的也是地址


1.基本数据类型

==比较的是值

equals()是不能使用的(因为eauqls()是Object类的方法,对象才能调用)

例:

int a=100; 

int b=100; 

System.out.println("a=b"+(a==b));//true 

System.out.println("a.equals(b)"+a.equals.(b));//编译报错


2.String和包装类

==比较的是内存中存放的地址

equals()比较的是值,因为它们重写了Object的equals()方法(类似还有Math,Date等值类型的类)

 

String部分

例如

String s1="hello"

String s2="hello";        

String s3=new String("hello"); 

String s4=new String("hello");   

String s5 = s3; 

String s6 = new String(s3);       

System.out.println("s1=s2"+(s1==s2)); 

System.out.println("s1=hello"+(s1=="hello")); 

System.out.println("s3=s4"+(s3==s4)); 

System.out.println("s5=s3"+(s5==s3)); 

System.out.println("s3=s1"+(s3==s1)); 

System.out.println("s5=hello"+(s5 =="hello")); 

System.out.println("s6=hello"+(s6 =="hello")); 

System.out.println(s1.equals(s2)); 

System.out.println(s3.equals(s1)); 

System.out.println(s3.equals(s4)); 

输出结果:

s1=s2 true

s1=hello true

s3=s4 false

s5=s3 true

s3=s1 false

s5=hello false

s6=hello false

true

true

true

是不是觉得一脸懵逼,摸不着头脑?

看了下面string两种赋值方法你一定会茅塞顿开

 

要知道String的两种赋值方法:

① " "直接赋值法

② new关键字法

第一种直接赋值法Jvm会先去常量池中检测该字符串是否存在,若存在不创建直接地址指向,共享此字符串,否则创建新的字符串,类似Integer的自动装箱,

第二种new创建的会直接在堆中开辟内存空间

所以s2和s1都指向常量池中hello字符串

而s3和s4分别在中开辟了内存,分别指向不同地址

s3==s1前者内存为堆后者为常量池,自然有s3==s1为false

 

包装类部分

注意Integer的享元模式:-128~127之间的数值在自动装箱的过程中,如果内存中存在相同数值的Integer类对象,则会共享此对象

 

看完下面的部分你就会明白

 

首先要知道包装类的自动装箱和自动拆箱机制

大家一定都见过这个语句Integer i= 5;

在jdk1.5以前,这样的代码是错误的,必须要通过Integeri = newInteger(5);这样的语句实现;而在jdk1.5以后,Java提供了自动装箱的功能,只需Integer i= 5; JVM会帮我们自动装箱,即基本数据类型转为包装类

相应的,包装类到基本数据类型的过程就是拆箱;如

Integeri =5

intj =i;//自动拆箱



底层源码:

装箱过程是通过调用包装器的valueOf方法实现的,而拆箱过程是通过调用包装器的xxxValue方法实现的。(xxx代表对应的基本数据类型)



注意:

Integer i=new Integer(xxx) 不会触发自动装箱的过程

Integeri=xxx;才会触发;

 

例如

Integer i1= new Integer(100);//手动装箱 

Integer i2= newInteger(100); 

System.out.println("i1=i2" + (i1 == i2));//false 

System.out.println("i1.equals(i2)"+i1.equals(i2));//true 

符合我们的预期,因为i1和i2是不同的对象不同的地址

Integer i1= 200;//自动装箱 

Integer i2= 200; 

System.out.println("i1=i2" + (i1 ==i2));//false 

符合我们的预期,因为i1和i2是不同的对象不同的地址

Integer i1= 100; 

Integer i2= 100; 

System.out.println("i1=i2" + (i1 ==i2));//true 

好奇怪?换个数值结果竟然不一样?难道i1和i2是同一个对象吗?

结论:此时的i1和i2指向同一对象,原因是Integer比较特殊,在自动装箱过程中,对于-128~127的值,它们被装箱为Integer对象后,会存在内存中被重用,始终只存在一个对象,而如果超过-128~127的值,被装箱后的Integer对象并不会被重用,相当于new一个新的Integer对象

 

另外包装类==基本数据类型 比较的也是值

Integer i1= 200; 

Integer i2= 100; 

Integer i3= i2+100;//结果300不在-128~127,自动装箱时产生新的对象 

System.out.println("i1=i2+i0" + (i1 == i3));//false 

int i=200; 

System.out.println("i1=i"+(i1==i));//true 

System.out.println("i1=i2+100"+(i1==i2+100));//true 

因为i2+100运算完得到200,还没有来得及自动装箱就和i1进行了比较

 

包装类例:

Integer i1= newInteger(100); 

Integer i2= newInteger(100); 

Integer i3= 200; 

Integer i4= 200; 

Integer i5= 100; 

Integer i6= 100; 

System.out.println(i1.equals(i2)); 

System.out.println("i1=i2" + (i1 == i2)); 

System.out.println("i3=i4" + (i3 == i4)); 

System.out.println("i5=i6" + (i5 == i6)); 

System.out.println("i5=i6+0"+(i5==i6+0)); 

输出结果:

true

i1=i2 false

i3=i4 false

i5=i6 true

i5=i6+0 true

 

3.继承Object的类

== 比较的是地址

equals()比较的是地址,没有重写Object类中的equals(),比较两个对象的引用是否相等

 

例如

Object obj1=new Object();

Object obj2=new Object();

System.out.println(obj1==obj2);

System.out.println(obj1.equals(obj2));

StringBuffer s1=new StringBuffer();

StringBuffer s2=new StringBuffer();

System.out.println(s1==s2);

System.out.println(s1.equals(s2));

输出结果:

false

false

false

false

 

equals()和hashcode ()的比较:

当比较大量数据的时候hashcode()比equals()效率高

 

比如向hashset(不允许重复)集合中有1000个元素,添加新元素的时候

equals:调用这个元素的equals()方法,遍历所有元素依次对比,没有重复的话添加

hashcode:调用这个元素的hashcode()方法,定位到相映的物理位置上

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

如果已经有元素了,就调用equals方法与新元素进行比较,相同则不存,不相同的话,也就是发生了Hash key相同导致冲突的情况,那么就在这个Hash key的地方产生一个链表,将这些元素串在一起

 

equal()相等的两个对象他们的hashCode()肯定相等

hashCode()相等的两个对象他们的equal()不一定相等,因为可能会发生Hash散列值冲突

 

所以当有大量元素需要进行比较的时候先用hashcode()比较,不相等则两个元素不等。如果hashcode()相等,再调用equals()比较,如果equal()也相同,则表示这两个元素相同。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值