==: 比较的是变量(栈)内存中存放的对象的(堆)内存地址,用来判断两个对象的地址是否相同,便是否是指相同一个对象。比较的是真正意义上的指针操做。html
equals:用来比较的是两个对象的内容是否相等,因为全部的类都是继承自java.lang.Object类的,因此适用于全部对象,String中的类是重写了object类里的equal()方法,而在本来的object类中,返回的是==的判断,若是没有对该方法进行覆盖的话,调用的仍然是Object类中的方法。java
hashCode : Object 的 native方法 , 获取对象的哈希值,用于肯定该对象在哈希表中的索引位置,它其实是一个int型整数。算法
在Java中有八种基本数据类型:数组
浮点型:float(4 字节), double(8 字节)this
整型:byte(1 字节), short(2 字节), int(4 字节) , long(8 字节)spa
字符型: char(2 字节).net
布尔型: boolean设计
对于这八种基本数据类型的变量,变量直接存储的是“值”,基本数据类型之间的比较须要用双等号(==),由于他们比较的是值指针
接口、类、数组等非基本数据类型code
Java中的字符串String属于引用数据类型。由于String是一个类
引用类型的变量存储的并非“值”自己,而是与其关联的对象在内存中的地址,当他们用(==)进行比较的时候,比较的是他们在内存中的存放地址,因此,除非是同一个new出来的对象,他们的比较后的结果为true,不然比较后结果为false。由于每new一次就会从新开辟一个新的堆内存空间
String s1 = "小新";
String s2 = "小新";
System.out.println(s1 == s2); //true
String str1 = new String("小新");
String str2 = new String("小新");
System.out.println(s1 == str1); //false
System.out.println(str1 == str2); //false
复制代码
s1 == s2为true,是由于s1和s2都是字符串字面值"小新"的引用,指向同一块地址,因此相等。
s1== str1为false,是由于经过new产生的对象在堆中,str1是堆中变量的引用,而s1是指向字符串字面值"小新"的引用,地址不一样因此不相等。
str1 == str2为flase,是由于即便内容相同,因为不是指向同一个对象,也会返回false。
equals,是Objec类的方法,源代码以下:
public boolean equals(Object obj) {
return (this == obj);
}
复制代码
可见Objec的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;
}
}
return false;
}
复制代码
使用equals方法,内部实现分为三个步骤:
所以,对于 equals 方法:
hashCode 方法是基类Object中的 实例native方法,所以对全部继承于Object的类都会有该方法。
他的源码以下:
public native int hashCode();
复制代码
说明是一个本地方法,它的实现是根据本地机器相关的。固然咱们能够在本身写的类中覆盖hashcode()方法,好比String、Integer、Double等这些类都是覆盖了hashcode()方法的。例如在String类中定义的hashcode()方法以下:
public int hashCode() {
int h = hash;
if (h == 0) {
int off = offset;
char val[] = value;
int len = count;
for (int i = 0; i < len; i++) {
h = 31 * h + val[off++];
}
hash = h;
}
return h;
}
复制代码
想要弄明白hashCode的做用,必需要先知道Java中的集合。 总的来讲,Java中的集合(Collection)有两类,一类是List,再有一类是Set。前者集合内的元素是有序的,元素能够重复;后者元素无序,但元素不可重复。这里就引出一个问题:要想保证元素不重复,可两个元素是否重复应该依据什么来判断呢? 这就是Object.equals方法了。可是,若是每增长一个元素就检查一次,那么当元素不少时,后添加到集合中的元素比较的次数就很是多了。也就是说,若是集合中如今已经有1000个元素,那么第1001个元素加入集合时,它就要调用1000次equals方法。这显然会大大下降效率。
因而,Java采用了哈希表的原理。哈希(Hash)其实是我的名,因为他提出一哈希算法的概念,因此就以他的名字命名了。哈希算法也称为散列算法,是将数据依特定算法直接指定到一个地址上,初学者能够简单理解,hashCode方法实际上返回的就是对象存储的物理地址(实际可能并非)。
这样一来,当集合要添加新的元素时,先调用这个元素的hashCode方法,就一会儿能定位到它应该放置的物理位置上。若是这个位置上没有元素,它就能够直接存储在这个位置上,不用再进行任何比较了;若是这个位置上已经有元素了,就调用它的equals方法与新元素进行比较,相同的话就不存了,不相同就散列其它的地址。因此这里存在一个冲突解决的问题。这样一来实际调用equals方法的次数就大大下降了,几乎只须要一两次。
1.使用hashcode方法提早校验,能够避免每一次比对都调用equals方法,提升效率
2.保证是同一个对象,若是重写了equals方法,而没有重写hashcode方法,会出现equals相等的对象,hashcode不相等的状况,重写hashcode方法就是为了不这种状况的出现。