程序员的公众号:源1024,获取更多资料,无加密无套路!
最近整理了一份大厂面试资料《史上最全大厂面试题》,Springboot、微服务、算法、数据结构、Zookeeper、Mybatis、Dubbo、linux、Kafka、Elasticsearch、数据库等等
获取方式: 关注公众号并回复 666 领取,更多内容持续奉上
HashMap的底层数据结构主要由数组和链表(或红黑树)组成。
HashMap内部维护了一个Entry数组,用于存储键值对对象Entry。数组的每个元素都是一个单向链表的头节点,如果发生哈希冲突(即两个不同的键经过哈希运算得到的数组索引位置相同),则将新的键值对添加到对应索引位置的链表中。
1. 哈希表
HashMap主要依赖于哈希表(数组)来存储数据。哈希表中的每个元素被称为“bucket”。数组的每个位置(bucket)都可以存放一个元素(键值对),数组的索引是通过键的哈希码经过哈希函数计算得来的。这样我们就可以通过键快速定位到数组的某个位置,取出相应的值,这就是HashMap快速获取数据的原理。
2. 链表
在理想的情况下,哈希函数将每个键均匀地散列到哈希表的各个位置。但在实际中,我们可能会遇到两个不同的键计算出相同的哈希值,这就是所谓的“哈希冲突”。HashMap通过使用链表来解决这个问题。
当哈希冲突发生时,HashMap会在冲突的bucket位置增加一个链表,新的元素会被添加到链表的末尾。每个链表中的元素都包含了相同哈希值的键值对。所以在查找元素时,如果遇到哈希冲突,HashMap需要进行一次线性查找。
链表节点包含键、值和指向下一个节点的指针。在Java 8之后,当链表长度达到一定阈值时(默认为8),链表会自动转换为红黑树,以提高查找效率。
3. 红黑树
从Java 8开始,如果链表的长度超过一定的阈值(默认为8),那么链表会被转换为红黑树。
红黑树是一种自平衡的二叉搜索树,它的插入、删除和查找操作的时间复杂度都是O(log n),相比于链表,红黑树在查找效率上更高。
4. 扩容与重新哈希
HashMap在初始化时,会有一个默认的初始容量(16),并且有一个加载因子(0.75)。当HashMap的大小(也就是已经存储的键值对数量)超过 容量*加载因子 的时候,HashMap会进行扩容,新的容量是原来的两倍,并且会进行重新哈希,将已经存在的元素重新放入新的bucket位置。
总结
HashMap的底层数据结构包括:哈希表(数组)、链表和红黑树。通过哈希函数将键映射到数组索引位置,可以快速定位到对应的链表或红黑树,然后在链表或红黑树中进行查找、插入或删除操作。HashMap通过哈希表的数据结构,实现了高效的键值对存储和查找。
系列文章索引
MyBatis的插件能在哪些地方进行拦截?
了解MyBatis的缓存机制吗
面试官:谈谈对volatile的理解
Spring中用到了哪些设计模式
面试官:说一下SQL的执行过程
线程池的工作原理