equals和==的应用场景有2中,一种是常规的字符串比较,另一种是对象的比较。
一.字符串比较:
1.场景一:
String c = "123";
String d = "123";
System.out.println(c==d);
System.out.println(c.equals(d));
结果
true
true
可见= =和equals都是true。
其中= =是查看的地址值也就是hashcode值及存储位置(hashcode相等,==不一定为true,其中hash值相当仅代表起哈希值相等,并不一定能得出键值对相等)
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;
}
其中先判断了一下类是否相同,然后判断是否属于其子类,判断长度是否相同,然后进行遍历,对其进行比对(其中为什么用while (n-- != 0),我还好奇去百度了一下,不得不说,底层的工程师真的是对性能方面有很深的研究,while (n-- != 0)是根据这个场景性能消耗最小的遍历方法,如果是我肯定就是for(int i=0;i<n.length();i++)了),然后进行比对,没什么可说的了就是单纯判断字符串是否相等了。
所以字符串的比较相对来说==与equals在定义String变量的时候如果不是new的String对象,他们原理上就是判断字符是否相等,因为“123”是作为静态变量存储到常量池中,常量池存储到方法区中
1.场景一:
String c = new String("123");
String d = new String("123");
System.out.println(c==d);
System.out.println(c.equals(d));
结果:
false
true
根据第一种情况来解读这次结果,==判断的是地址值,他们的地址值肯定不同,因为是分别new出来的,为了校验地址值不同的这个想法我们可以把它打印出来
String c = new String("123");
String d = new String("123");
System.out.println("hashcode1:"+c.hashCode());
System.out.println("hashcode2:"+d.hashCode());
结果出乎了我的意料
c的hashcode:48690
d的hashcode:48690
于是我就有一个想法,所以去百度,百度过程中看到了这段话:
HashMap在存储数据计算hash地址的时候,我们希望尽量减少有同样的hash地址,所谓“Hash冲突”。如果使用相同hash地址的数据过多,那么这些数据所组成的hash链就更长,从而降低了查询效率!所以在选择系数的时候要选择尽量长的系数并且让乘法尽量不要溢出的系数,因为如果计算出来的hash地址越大,所谓的“冲突”就越少,查找起来效率也会提高。
可见下图:散列中的存储虽然地址值相同,但是同样的地址值后面每个对象的存储是链值形式存储,所以两个对象并不是同一个地址值就一定相等,他们只是放到一个地址值而已,相反这样会对性能有损耗。所以不建议重写hashcode方法,分配固定的地址值。
为了验证上面的想法有以下例子可以看出:
String c = new String("123");
String d = c;
System.out.println(c==d);
System.out.println(c.equals(d));
结果为
true
true
一.对象比较:
首先创建一个测试类
public class hashCodeTest {
public hashCodeTest(String userName) {
this.userName = userName;
}
private String userName;
private String password;
private Integer age;
//重写hashCode() 和equals()方法
@Override
public int hashCode() {
return 1;
}
public static void main(String[] args) {
hashCodeTest a = new hashCodeTest("zty");
hashCodeTest b = new hashCodeTest("zty");
System.out.println((a.hashCode()+"").equals(b.hashCode()+""));
System.out.println("a:"+a);
System.out.println("b:"+b);
System.out.println(a==b);
System.out.println(a.equals(b));
/* String c = new String("123");
String d = c;
System.out.println(c==d);
System.out.println(c.equals(d));*/
}
}
运行其main方法结果为
true
a:test.hashCodeTest@1
b:test.hashCodeTest@1
false
false
根据字符串比较我们可以得到==不仅比较的是字符串是否相同,还比较hashcode,然后在比较分配的内存地址,如果都相同,才会返回true。
所以我们看下Object的equals方法:
如下为底层代码
public boolean equals(Object obj) {
return (this == obj);
}
所以可得对象的==与equals是相同的,所以这也是我们基本不使用对象的equals方法的原因。