说清为什么要重写hashcode方法
hashCode()到底有什么用,为啥一定要和equals()重写
HashCode()是native方法,重写后,会把HashCode()转换成int数值返回
int数值返回的就是哈希码,也称散列码 . 作用就是确定对象在哈希表的索引位置
哈希表 :JDK8 之后 是 数组 +链表 +红黑树
例子 : 有一万+ 的对象,需要存储起来,不允许存储重复的对象并且可以随时获取对象. 怎么做?
可能有的朋友想到数组存储,当把对象放在数组中,每判断一次,都需要遍历数组,挨个比较,使用equals ,如果equals为真,就找到了对象,如果为false,就是假.但是这样子的效率太低.时间复杂度O(n)
怎么样提高效率.使用hashCode得到的哈希码就派上了用场. 通过哈希码和数组长度取余,这样子就得到了数组要存放的位置 . 例如,数组长度是10,哈希值为17,就把这个对象放在数组下标为7的位置上.这样子无论是获取元素还是存储元素,通过数组下标只需要操作一次.时间复杂度为O(1) .. 确定索引位置就可以大幅度提高效率
还有一个很大的问题.哈希码是可能重复的,哈希值是根据一定的逻辑计算出来的int值,两个不同的对象可能重复哈希码.就这就哈希冲突.
如果发生Hash冲突时,我们要先比较两个对象的是否相同,如果相同,就是重复元素,就不需要存储了. 如果不相等, 就要想办法把两个哈希冲突的元素存储起来
怎么判断两个对象是否相等,肯定使用equals方法
hashcode方法定位索引位置,equals方法判断两个对象是否相等. hashcode虽然效率高,但是会发生哈希冲突.当哈希冲突时,就要通过equals方法来判断对象是否相等
如果只重写了HasCode方法,当发生哈希冲突时,即两个对象相等,也不会判定重复,会导致数组里面存储一大堆重复对象
(解释 : 两个相同的对象,计算出的哈希值一样,会放到一个数组里面,这样会有很多的重复对象.重复的对象,违背了不可重复key具有唯一性,这样子肯定是不行的)
如果只重写了equals方法,两个相等的对象,内存地址还是不会相等,还是会存在重复元素的问题.所以两个方法最好都重写
(解释 : 重新了equals方法,你new了两个相同的对象,内存地址肯定是不相同的, 那么放到集合里面,会认为是不一样的数据, 还是可能会放到同一个数组里面,这样子还是会导致元素重复)
总结: hashcode 和 equals
hashcode 方法 用来在最快时间判断两个对象是否相等,并定位索引位置,不过可能会出现误差
equals 方法 判断两个对象是否绝对相等
hashcode方法保证性能, equals方法保证可靠
一些问题及解决
问题 : hashcode相同的话旧的数据不应该是被覆盖,为什么会存储大量重复数据呢
假设一批对象属性值一模一样,重写了hashCode没重写equals方法,那hashCode就会相同,但equals不相同,就会判定这些对象都不相等,进而不会覆盖,会将这一批对象都存储起来
集合里面有哪些不可重复的
HashSet : 底层是哈希表的数据结构,无序不可重复
LinkedHashSet: 底层是双向链表+哈希表 . 有序不可重复
Map集合的key都是不可重复的 如果key重复的话,数据就会覆盖
如果要保证不重复,必须得要保证key的唯一性