1 HashCode
它是通过hash函数得来的,通俗地说就是通过某一种算法得到的,hashcode就是在hash表中有对应的位置。
hashcode比较的是哈希码,哈希码是由特定的哈希算法得出来的。
物理地址说的是对象存放在内存中的地址。
hashcode代表对象的地址是对象在hash表中的位置,通过对象的内部地址(物理地址)转换成一个整数,然后该整数通过hash函数的算法就得到了hashcode。
举例:hash表中有hashcode为1,hashcode为2,3,4,5,6,7,8这样8个位置。
有一个对象A,A的物理地址转换为17(假如),然后通过取余算法,17%8=1,那么A的hashcode就为1,且A就在hash表中1的位置。
2 hashCode()方法和equals方法的作用其实一样,在Java里都是用来对比两个对象是否相等一致,那么既然已经有equals方法了,为什么还要hashCode方法呢?
因为一般情况下重写的equals方法里比较的比较全面比较复杂,那么这样就效率比较低了。而利用hashCode方法进行对比,则只要生成一个hash值进行比较就可以了,效率很高,那么hashCode()既然效率高为什么还要equals()呢?
因为hashCode()并不是完全可靠的,有时候不同的对象生成的hashcode也会一样,所以并不是绝对可靠。Java中JDK规定:
equals相等的两个对象他们的hashcode肯定相等,也就是用equals对比是绝对可靠的。
hashcode相等的两个对象他们的equals不一定相等,也就是hashCode不是绝对可靠的。
所以对于需要大量并且快速对比的话用equlas方法去做显然效率太低,解决方式就是:
每次需要对比的时候,首先用hashcode去对比,如果hashcode不一样,那么表示这两个对象肯定不相等(也就是不必用equals去再对比了),如果hashcode相同,此时再对比他们的equals(),如果equals也相同,那么这两个对象是真的相同了,这样既能大大保证效率也保证了对比的绝对正确性。
3 为什么重写equals()方法时,必须要求重写hashCode()方法。
在实际开发中,如果我们自定义的类需要进行比较操作,就一定也需要重写equlas方法,那么为什么重写equlas方法时,必须要求重写hashCode方法呢?
Effective JAVA一书中这样说到:在每个覆盖了equals方法的类中,也必须覆盖hashCode方法,如果不这样做的话,就会违反Object.hashCode的通用的约定。从而导致该类无法结合所以散列(哈希)的集合一起运作,这样的集合包括HashMap,HashSet,HashTable。
我们使用hashcode方法目的就是为了提高程序的效率。
程序先进行hashcode的比较,如果不同,那就不必要进行equals的比较了,这样就大大减少了equals的比较的次数了,这样对比方式大大的提高了效率,一个很好的例子就是在集合中使用。
我们都知道Set集合是无序的,也是不能添加重复的元素,那么怎么能保证加入的元素不是重复的呢?如果单靠equals方法比较的话,如果元素集合中有100000个元素,那么当放入1000001个元素时,难道要将前面的所有元素都比较一遍吗?那这个时间复杂度就很高了。
因为hashcode就应运而生了,JAVA就采用了hash表利用哈希算法也叫散列算法,就是将数据对象根据对象的特征使用特定的算法将其定义到一个地址上,那么在后面定义进来的数据只要看对应的hashcode地址上是否有值,大大提高效率。
重写hashCode方法的原因就是:为了保证是同一个对象,在equals比较相同的情况下,hashcode的值也必定相同。
用代码举例说明下:
第一种情况:只重写equals方法,不重写hashcode方法。
如果重写了equals而未重写hashcode方法,那么可能就会出现两个对象的equals方法返回值相等而hashcode不相等的情况,这就违背了hashcode的规则,两个对象相等那么他们的hash值也一定要相等。这样就产生了矛盾。
如果我们在重写了equals()时,也重写了hashcode()方法。
从Student类重写后的hashcode方法中可以看出,重写后返回新的hash值与Student的两个属性有关。
一句话就是实现两个对象的equals()方法相等,那么hashcode也要一定相等。
网友评论