目录
一、Object类中的常见方法有哪些?
有几个本地方法:
hashCode()、clone()、getClass()、notify()、notifyAll()、wait带一个参数(超时时间)的
还有几个public的方法
toString()、equals()、wait()、wait(超时时间,+纳秒)
还有一个protected的方法 上面还有一个protected方法(clone)
finalize
二、== 和 equals()的区别
如果是基本数据类型比较的就是值 而如果是引用数据类型 == 其实比较的也是值 只不过是引用地址值
equals方法它是对象的方法 只有对象才有这个方法 这个如果不重写Object类中的equals方法
那么和==一样,也是比较的地址值 如果重写了那么可以比较对象的内容是否相同
三、hashCode()有什么用?
hashCode()是一个本地方法,获取的就是对象的哈希值 也叫散列值
它的作用体现在键值对上面,通过hash值能够快速的找到对象,作用就是大大的提高了检索的效率
四、为什么要有hashCode?
这个在HashMap或者是HashSet中作用很明显
它们在放入一个新元素时,需要先获取到对象的hash值,当然hashMap不仅仅只是简单的通过hashCode方法获取到hash值然后就直接映射到数组下标,而是为了使得散列更为的均匀(也就是使得不同的对象尽可能的hash值不同,从而降低hash冲突的发生的概率),而是继续二次hash,也就是摆动函数,就是hashMap中重写的那个hashCode方法,当算出那个hash值之后,然后使用
hash & (len-1)得到数组下标,这个其实就是hash%len的结果 至于为什么要这样是因为&运算更快,而要使得 这两个的表达式结果一样,就要len 的值必须是2的幂次方(这也就解释了为什么HashMap的长度必须是2的幂次方)
它的插入逻辑上下面这样:
1. 如果说算出来的下标处没有元素,那么直接插入 因为这样的话 hash值肯定就不一样了,因为如果hash值一样的话,那么计算出来的下标一定一样,既然hash值都不一样那么可以肯定两个对象肯定不一样 因为我们提前就要求了 如果两个相同的对象,那么hash值也一定相同,既然这里hash值不同,那么肯定就是不同对象了,因此可以直接进行插入。(要达到这样的效果需要满足:相同的对象hash值一定相同,而原本如果不去重 写hashCode方法的话,其计算出来的hash值是随机的,因此两个相同的对象的hash值可能不一样 根据如果hash值不同那么就直接认为两个对象不同 那么就能直接插入,导致出现重复 所以就得必须重写hashCode方法)
2. 如果算出来的地方正好也有元素,那么这两个对象的hash值可能相同也可能不同,因为hash值相同的话其下标肯定一样进而冲突,而hash值不同 因为数组的长度有限那么也有可能就是不同的hash值计算出相同的下标,进而导致冲突
所以得分情况讨论了现在:
首先是直接比较hash值
如果是hash值不同那可以直接认为是两个不同的对象,则直接放上
如果说hash值相同,也不能直接认为两个对象相同
我们是说两个相同对象hash值相同,可是并没有说两个对象hash值相同两个对象就相同
也就是 前者可以推导出后者但是后者推导不出前者
这是因为两个不同的对象如果散列函数不够厉害的话,就可能导致两个不同的对象计算出相同的hash值(所以提高散列函数的精确性能够降低两个不同对象出现相同的hash值的情况,进而降低hash冲突的概率)
所以即使不同的对象也有可能出现相同的hash值,因此不能直接通过hash值相同就直接认为两个对象一样,所以现在就需要调用终极武器:equal方法来最终确定两个对象到底是否相同了
一旦出现了调用equals方法了,其实就是可能是因为两个不同对象出现相同hash值的情况,其实归根结底就是散列函数不够高明,如果高明的话,那么不同的对象自然也就不会是相同的hash值,虽然可能还是会因为数组长度的原因导致冲突,但如果抛出这个,那么自然也就能插入了,也就不需要使用终极武器(equals方法了)。
因此在这个插入过程中,hashCode的作用就很明显了,能够通过hashCode快速判断当前元素是否可以插入 还能避免重复 相较于如果只使用equals方法,直接一个一个的比效率高了很多
重写hashCode的作用:
使得相同对象有相同的hash值 为不同对象就是不同的hash值,为如果hash值不同那么对象一定不同提供了理论依据
高明散列算法的作用:
使得尽可能的不同的对象有不同的hash值,从而避免冲突,避免再去调用equals方法,提高效率
降低hash冲突可以:
1. 高明的散列算法
2. 数组长度长一点(当散列算法很高明的时候,虽然是不同的对象hash值已经不同了,但是会去对数组长度取余,所以说如果长度不够的话,即使是不同的对象可能还会是相同的数组下标,导致发生冲突)
使得整个理论成立:
重写hashCode方法
解决散列算法不够高明的问题,最后的杀手锏:
重写equals方法
因此 重写hashcode 重写equals 高明的散列算法这三个一个不能少
五、为什么重写equals必须要重写hashCode?
上面已经说了,重写hashCode是整个理论的基础
正是有了这个理论才能使得 快速的插入数据 判重 而非一个一个equals的低效率