Hash是散列的意思, 就是把任意长度的输入, 通过散列算法(哈希算法)变成固定长度的输出, 该输出就是散列值
- 不同的关键字通过散列算法得到同一个散列地址, 称为哈希碰撞
- 如果两个Hash值不同, 那么这两个Hash值对应的输入肯定不相同
- HashCode的存在主要是为了查找的快捷性, HashCode是用来在散列结构中确定对象的存储地址的
- 如果两个对象equals相同, 那么两个对象的hashcode一定相同
- 如果对象的equals方法被重写, 那么hashcode方法也建议重写
- 如果两个对象的hashcode相同, 不代表两个对象就相同, 只说明两个对象在哈希结构中存储在同一个位置
哈希冲突
如果两个不同的元素, 通过哈希函数, 得到相同的存储地址怎么办? 也就是说, 我们对某个元素进行哈希运算, 得到一个存储地址, 进行插入的时候, 发现这个位置上已经有值了, 这就是哈希冲突, 也叫哈希碰撞。所以设计好的哈希函数非常重要, 好的哈希函数可以尽可能的保证散列地址分布均匀,减少冲突的产生。但数组是一块连续的内存空间, 设计再好的哈希函数也不可能避免冲突。那么哈希冲突如何解决呢?
哈希冲突的解决方法有多种:
- 开放地址法 发生冲突, 继续寻找下一块未被占用的存储地址
- 链地址法
举个例子:
- 假设内存中有0 1 2 3 4 5 6 7 8这8个位置, 如果有个数要放在这8个位置的其中一个位置上, 如果不用哈希算法而任意存放, 那查找的时候就需要到8个位置上挨个去找
- 使用Hashcode则会效率高很多, 将这个数的hashcode % 8, 然后把这个数放在取得余数的那个位置, 然后每次查找该类时, 直接将这个数的hashcode % 8, 然后查找余数的那个位置
- 如果算出来余数的位置上有值, 那就要取决于算法的实现了, 比如ThreadLocal中的做法就是从算出来的位置向后查找第一个为空的位置, 放置数据; HashMap的做法就是通过链式结构连起来。只要保证存的时候和取的时候保持一致就行