== 比较
java中的数据类型,可分为两类:
1.基本数据类型,也称原始数据类型
byte,short,char,int,long,float,double,boolean
他们之间的比较,应用双等号(==),比较的是他们的值。
2.引用类型(类、接口、数组)
当他们用(==)进行比较的时候,比较的是他们在内存中的存放地址,所以,除非是同一个new出来的对象,他们的比较后的结果为true,否则比较后结果为false。对象是放在堆中的,栈中存放的是对象的引用(地址)。先看下虚拟机内存图和代码:
equals 比较
-
equals是object的方法,所以每个类都有equals方法,区别在于是否重写了该方法;
-
很明显Object定义的是对两个对象的地址值进行的比较
//equals 源码
public boolean equals(Object obj) {
return (this == obj);
}
- String 类重写了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;
}
hash比价
hash比较其实就是计算一个对象的hash值
hash算法的大致过程:
- 由键key得出hashCode
- 由hashCode算出hash值
- 由hash算出于数组中的下标
- 1-我们知道无论是键还是值,都应该是一个对象,不同的对象具有不同的存储地址,hashCode得到的哈希值就是根据对象的地址转化而来的。
-
2:在hashmap中,对hashcode方法进行了重写,重写的时候用到了hash算法,即把hashcode的高16位与低16位进行异或运算,得到hash值。
-
3:把hash值与数组长度减一进行“与”运算得到下标。(这里需要注意的是,因为数组的长度始终是2的次方幂,这里的与运算,就相当于给length-1取模运算)
为什么在重写equals方法的时候要重写hashcode的方法?
我们知道判断的时候先根据hashcode进行的判断,相同的情况下再根据equals()方法进行判断。如果只重写了equals方法,而不重写hashcode的方法,会造成hashcode的值不同,而equals()方法判断出来的结果为true。
在Java中的一些容器中,不允许有两个完全相同的对象,插入的时候,如果判断相同则会进行覆盖。这时候如果只重写了equals()的方法,而不重写hashcode的方法,Object中hashcode是根据对象的存储地址转换而形成的一个哈希值。这时候就有可能因为没有重写hashcode方法,造成相同的对象散列到不同的位置而造成对象的不能覆盖的问题。
总结:
- 在特殊容器中,比如HashMap中,它是链表+数组的结构,链表是key的hash值来确定的位置
- 不重写hashcode的方法,会造成hashcode的值不同,而equals()方法判断出来的结果为true的数据放在不同的节点位置