目录
两个对象的hashcode一样那么equals一定一样吗?&& 两个对象的equals一样那么hashcode一定一样吗?
HashMap m = new HashMap<>底层数组多大?
HashMap m = new HashMap<25>底层数组多大?
一、概念
哈希算法与哈希表
- 哈希算法就是把任意长度的输入通过散列算法变为固定长度的输出,这个输出的结果就是散列值。
- 哈希表也叫做散列表,他是通过key直接访问在内存存储位置的数据结构,在具体实现上,我们通过哈希函数把key映射到表中的某个位置,来获取这个位置的数据从而加快查询速度
- 哈希冲突是由于哈希算法被计算的数据是无限的,而计算后的结果范围有限,所以会出现不同数据经过计算后得到的散列值相同
二、哈希碰撞与解决
解决哈希冲突的四种方法
- 开发地址法:也叫线性探测法,就是从发生哈希冲突的位置开始按照一定的顺序依次此功能哈希表中找到一个空闲位置将该元素存储。
- 链式寻址法:将存在哈希冲突的key,以单向链表的方式来存储。
- 再哈希法:当通过某个哈希函数计算出现冲突后,再使用另一个哈希函数计算散列值,直到不出现冲突为止。这种方法会增加计算时间,性能影响比较大
- 建立公共溢出区:将哈希表分为基本表与溢出表两个部分,出现哈希冲突的元素一律存放到溢出表中
HashMap解决哈希冲突
在jdk1.8版本中他是使用链式寻址法+红黑树解决哈希冲突问题的,其中红黑树是为了优化由于链表过长导致查询时间复杂度增加的问题,当数组长度超过64且单链表元素大于等于8时就会转变为红黑树
三、代码实现
public class HashMap <K, V>{
// 节点
static class Node<K, V> {
K key;
V val;
public Node<K, V> next;
public Node(K key, V val) {
this.key = key;
this.val = val;
}
}
// 底层数组
private Node<K, V>[] elem = new Node[16];
// 元素个数
private int size;
// 负载因子
private static final float DEFAULT_LOAD_FACTOR = 0.75f;
public boolean put(K key, V data) {
// 计算所在哈希桶
int index = key.hashCode() % this.elem.length;
// 遍历该哈希桶内链表
Node<K, V> cur = this.elem[index];
while (cur != null) {
// 如果已经存在key,就替换
if (cur.key.equals(key)) {
cur.val = data;
return false;