众所周知再JDK1.8之后,Java修改了String类型的底层源码,因为他们发现其实对于-128~127范围的字符更加常用,因此将底层的数组从char类型修改为了byte类型。
看到上面的方法可以发现,String类型的equals方法会先比较两个字符串的内存地址是否相等,如果是直接返回true,否则比较字符串的内容,如果内容相等返回true,否则返回false。
那么这和hashCode方法有什么关系呢?
总所周知,Java中所有的类都默认继承Object类,而Object类中有一个native的hashCode方法,因此所有的类都有一个native的hashCode方法
而hashCode方法在散列集合中会用到,比如HashTable、HashMap这些,当添加元素的时候,需要先判断元素是否存在,而如果直接使用equals方法去比较,那么效率非常低,此时通过的是对象的hashcode值进行取模后运算,如果table中没有这个对象相对应的hashcode的值,那么这个对象就可以存进去了,不用再进行任何比较。而如果已经存在了这个hashcode值,那么就需要进行equals方法进行对象比较,相同则覆盖,不相同直接插入。
所以这里就涉及到了一个冲突解决的问题,如果使用hashcode先判断对象是否相等,那么使用equals这个方法的次数就降低了,效率就自然提升了。
hashcode默认是JVM使用随机数生成的,两个随机对象,他们生成的hashcode值有可能相同。而如果这样子,再hash表中的提现就是所谓的hash冲突,通常使用链表或者线性探测来解决这个问题。
但是两个完全相同的对象,他们的内存地址指向同一个位置,也就是他们的hashcode一定是相同的。
那么在没有重写equals方法的情况下,x.equals(y)==true代表的就是x和y指向同一个内存地址,因为此时使用的是 == 进行判断。
那么他们的hashcode值也一定相同。
而如果重写了equals方法,但是没有重写hashCode方法,那么就会导致hashcode值可能不一样,而如果出现这种情况,就会导致这个类无法和所有的集合类一起工作。
对于散列集合,他们使用的是hashcode来判断是否是相同的,如果存储两个相同的对象,但是他们的hashcode值不同,那么就会导致这两个对象存储在hash表的两个不同的位置,然后当我们想要获取数据的时候,就会出现一个完全相同的对象,会存储在hash表的两个位置,就会破坏程序开发过程中我们约定俗成的规则,就会出现一些不可预料的错误。
所以在实际开发中,约定俗成:重写equals方法也必须重写hashCode方法。