HashMap大家都知道吧:先看看jdk1.7中的HashMap和jdk1.8中的有什么不一样
jdk1.7之前是数组加链表,扩容重新散列元素使用头插法(容易形成循环列表),数据元素通过散列函数获取位置下标,映射到桶数组对应位置,如果发生hash冲突,用拉链法解决冲突,不给初始大小默认16,给初始大小的话,也不是按照你给定的的初始大小创建的,他会像上寻找最近的2的n次方(例如你传17他向上寻找就是32,因为2的四次方<17<2的五次方),扩容因子为0.75,map中的元素数量超过他的大小×扩容因子就会进行扩容,每次扩容为之前的两倍大小(hashtable为两倍加一),HashMap是快速失败的(fail-fast),当 HashMap 在迭代过程中,元素被修改或者删除了,会抛出 ConcurrentModificationException 错误,最后——HashMap是线程不安全的。
jdk1.8之后HashMap加入了红黑树(数组加链表加红黑树),扩容重新散列元素使用尾插法(避免形成循环链表),如果链表长度>8&数组大小>=64,链表转为红黑树,如果红黑树节点个数<6 (因为如果设置为7的话,他要是7-8-7的反复,会一直转化会造成额外的资源开销,所以设置了一个类似缓冲区的东西)转为链表。
Tip:1.为什么不用二叉树或者平衡二叉树?
不用二叉树是因为红黑树是一种平衡的二叉树,插入、删除、查找的最坏时间复杂度都为 O(logn),避免了二叉树最坏情况下的O(n)时间复杂度(也就是最坏情况下,他的时间复杂度是高于红黑树的)。
不用平衡二叉树的原因是平衡二叉树是比红黑树更严格的平衡树,为了保持保持平衡,需要旋转的次数更多,也就是说平衡二叉树保持平衡的效率更低,所以平衡二叉树插入和删除的效率比红黑树要低(也就是平衡二叉树,他必须时刻保持平衡,怎么保持呢,只能旋转,旋转是不是要造成额外的开销)。
2.为什么链表大于8转化,7不行吗?
这个结果是根据泊松分布算出来的,别问啥是泊松分布,我也不会。
接下来重头戏,手写一个HashMap
首先,写肯定是写数组加链表那一款的,红黑树我也手撕不出来(看明白都费劲),不多比比,上代码:
注释都写的很详细了复制就能跑
先创建key和value两个对象,类型给object
import lombok.Data;
@Data
public class K {
private Object K ;
}
import lombok.Data;
@Data
public class V {
private Object V ;
}
然后是HashMap的实现代码,有点长但是请一定从头到尾敲一遍,注释我都写的很详细了,每一步都写了。
import com.example.demo.*;
public class Mapss<K,V> {
class Node<K, V> {
/**
* K hashmap的key
* V hashmap的value
* Node 用来实现数组+链表的
*/
private K key;
private V value;
private Node<K,V> next;
public Node(K key, V value) {
this.key = key;
this.value = value;
}
public Node(</

这篇博客详细解析了HashMap在JDK1.7和1.8版本的区别,包括1.7中的数组加链表结构及头插法扩容,1.8引入的红黑树优化,以及为何选择红黑树而非其他数据结构。作者还提供了手写HashMap的实现代码,涵盖了扩容、插入、查找等核心功能,并通过泊松分布解释了链表转红黑树的阈值设定。
&spm=1001.2101.3001.5002&articleId=122327383&d=1&t=3&u=51f76cfb463945c1925d483ee791c185)
1796

被折叠的 条评论
为什么被折叠?



