重写前:java
* ==表示两个对象的内存地址 * equals()也表示对象内存地址 * hashCode()表示该对象在JVM中的32位内存地址
重写后:
==仍表示两个对象的内存地址 equals()表示连个对象的值是否相等,相等就视为同一个对象 若是equals()方法重写,那么hashCode()方法也要重写,由于要保证同一个对象的hashCode值相等这样的规定。
根据javaAPI文档上的介绍:程序员
(1)、同一个对象的hashCode值必定相同,不管是否重写过equals()方法,也就是说重写过之后他们的值相等了,那么他们的hashCode也要保持相等,因此就也要重写hashCode()方法。算法
(2)、若是两个对象不相等,那么对这两个对象中的任一对象上调用 hashCode 方法不 要求必定生成不一样的整数结果。可是,程序员应该意识到,为不相等的对象生成不一样整数结果能够提升哈希表的性能。ide
好比重写后的hashCode方法以下:性能
@Override测试
public int hashCode() { final int prime = 31; int result = 1; result = prime * result + age; result = prime * result + ((name == null) ? 0 : name.hashCode()); result = prime * result + sex; return result; }
比较两个对象是否相等:this
(1)先比较连个对象的hashCode值是否相等,若是相等则比较(2)(由于不一样的对象也有可能hashCode值相等),若是不等则必定不是同一个对象code
(2)再比较equals()方法,若是相等则视为赞成对象,反之则不是同一个对象。**对象
二、hashCode()和equals()关系是什么?
明白几个原则:
equals相等的两个对象,hashcode必定相等。
equals不相等的两个对象,hashcode不必定不相等。
hashcode不相等,那么equals是必定不等的。
hashcode相等,equals可能相等,也可能不等。
解释下第四个原则:
就比如hashcode像是一个词典目录里的按字母为索引查找字,查一个“Z”拼音开头的词,下面等查到“本身”,“自我”,“知道”等词,用equals就是判断这些词语当中是否有相等的词,“本身”和“知道”两个词不相等的,因此equals值不等,但它们同属于"Z"开头的词因此它们hashcode值相等。索引
三、为何重写equals的同时也要重写hashCode呢?
hash算法是为了提升equals比较的效率而被发明出来的。这点在集合方面就能体现出来,就好比在List或Set集合里要比较是否有重复元素,当发现某个集合对象与另外一个集合对象equals比较的结果相等时,则中止查找返回true值,反之,返回false值。
但若是集合中有大量元素呢,假设一个集合A里有10万元素,并且另外一个比较的对象B中还可能没有重复的值,则意味着其实不用比较我都知道二者不相同,但程序依然会对集合A里遍历10万元素而后和B进行逐一排查。。。又或者当我要加入第100001个数据我要验证前面元素有重复值,就要跟前面10万个元素一一比较,效率可想而知很低。
而哈希算法就是Java系统首先调用对象的hashCode()方法得到该对象的哈希码表,而后根据哈希码找到相应的存储区域,若哈希码相同在取得该存储区域内的每一个元素与该对象进行equals方法比较,若不一样也就没有继续比较的必要了,这对于数量较大的状况效率就提升了很多,重写hashcode方法,最主要就是保证操做的元素在同一个对象里且值都没有重复,若没有重写hashcode,可能会出现将对象引用不一样,但元素彻底相同的集合进行操做。
下面写一个例子
package demo;
public class override_HshCode_Equals {
public int x;
public int y;
public override_HshCode_Equals(int x, int y) { this.x = x; this.y = y; } @Override public int hashCode() { //下面变量初始化值能够任意取 final int prime = 31; int result = 1; result = prime * result + x; result = prime * result + y; return result; } /** * equals返回false就说明没有重复项能够添加 * true是重复不能添加 */ @Override public boolean equals(Object obj) { if (this == obj) return true; if (obj == null) return false; if (getClass() != obj.getClass()) return false; final override_HshCode_Equals heClass = (override_HshCode_Equals) obj; //这里就对实例化对象里的x,y进行比较 if (x != heClass.x) { return false; } if (y != heClass.y) { return false; } return true; }
}
测试类
package demo; import java.util.HashSet; public class TestMain { public static void main(String[] args) { HashSet<override_HshCode_Equals> set = new HashSet<override_HshCode_Equals>(); override_HshCode_Equals heClass1 = new override_HshCode_Equals(1, 1); override_HshCode_Equals heClass2 = new override_HshCode_Equals(5, 5); override_HshCode_Equals heClass3 = new override_HshCode_Equals(1, 1); set.add(heClass1); set.add(heClass2); set.add(heClass3); set.add(heClass1); System.out.println("set数量=" + set.size()); } } 结果以下 set数量=2
注:重写override_HshCode_Equals类的hashCode至关于自定义返回了一个“哈希码”,对比x,y值是否相等,先比较hashcode值,heClass1(3,3)==heClass3(3,3),因此它们的hashcode值相等,可是heClass2的x,y和heClass1,heClass3的x,y值不等,因此hashcode不等,equals必定不等,因此heClass2对象是能够add进去的。前面说了heClass1和heClass3的hashcode值相等,而后进入equals进行对比,发现二者的对象都是相同的,根据程序add循序来看,因此heClass1是能够add进去的,而后heClass3和后面add(heClass1)都为重复项,就不会添加