剖析HashMap结构

参考视频:剖析HashMap源码

1、 图解数据结构【有图有真相】

在这里插入图片描述

在这里插入图片描述

HaspMap数据结构是:数组 + 链表
hashmap原理:
  采⽤数组+链表的结构来实现,添加元素时,⾸先计算key的hash值,然后根据这个hash值,定位到下标,如果冲突的话,则在该下标节点处链上⼀个链表,以头插法添加新元素为链表头结点,如果链表长度超过指定长度,则转换为红⿊树。hashmap解决冲突的办法叫做链地址法,或者叫拉链法
在这里插入图片描述
  在jdk1.8之后为了解决HashMap链表过程,导致遍历产生的时间过长,引入了红黑树进行了进一步优化。
  当链表长度太长(超过TREEIFY_THRESHOLD = 8)时,当Node[] table数组长度超过64(MIN_TREEIFY_THRESHOLD = 64)时,链表就转化为红黑树,利用红黑树快速增删改查的特点提高HashMap的性能。
在这里插入图片描述
1、HashMap的扰动函数怎么解释?

static final int hash(Object key) {
 int h;
 return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);
}

  key.hashCode()函数调⽤的是key键值类型⾃带的哈希函数,返回的数据是-2147483648到2147483648,基本上可以解决Hash冲突的问题了。但是这个数据在内存中需要很⼤的空间保存。

  右位移16位,正好是32bit的⼀半,⾃⼰的⾼半区和低半区做异或,就是为了混合原始哈希码的⾼位和低位,以此来加⼤低位的随机性。⽽且混合后的低位掺杂了⾼位的部分特征,这样⾼位的信息也被变相保留下来。

https://www.todaysoftmag.com/article/1663/an-introduction-to-optimising-a-h
ashing-strategy

扰动函数主要的作⽤就是为了降低Hash碰撞的发⽣

2、需要知道下⾯的位运算
⼀个求余的%等价为:X & (2^N - 1)?

SparseArray比较节省内存,如果我们对内存要求比较高,但是查找效率没那么高,就可以使用SparseArray
SparseArray核⼼特点:

  • 键值对形式进⾏存储,基于⼆分查找,因此查找的时间复杂度为0(LogN);
  • 由于SparseArray中Key存储的是数组形式,因此可以直接以int作为Key。避免了HashMap的装箱拆箱操作,性能更⾼且int的存储开销远远⼩于Integer;
  • 采⽤了延迟删除的机制;

常⽤数据结构总结:
数组(Array)、链表(Linked List)、堆(Heap)、栈(Stack)、队队列列(Queue)、树(Tree)、图(Graph)、散散列表列表(Hash)
数组:有限个相同类型的数据的有序的集合。
优点:

  • 按照下标查询,查询速度快。
  • 按照下标遍历⽅便。

缺点:

  • 插⼊⼀个其它的需要移动位置,故⽽插⼊慢。
  • 数据类型单⼀。

链表:物理存储单元上⾮连续、⾮顺序的存储结构,数据元素的逻辑顺序是通过链表中的指针链接次序实现的。分单向链表、双向链表、循环链表。
优点:

  • 根据左右两个指针便可插⼊,故⽽插⼊速度快。
  • 不需要初始化容量。

缺点:

  • 需要遍历整个链表查询,故⽽查询慢。
  • 含有⼤量指针域,占⽤空间⼤。

:⼀种特殊的树,完全⼆叉树。分⼤顶堆和⼩顶堆。

  • ⼤顶堆:⼩数据的元素插⼊、删除快,⼤数据的元素慢。
  • ⼩顶堆:⼤数据的元素插⼊、删除快,⼩数据的元素慢。

堆本质:二叉树的特性来维护一维数组
堆和树的区别:从数据结构上来讲最本质的区别树用指针来修饰;堆不使用指针,性能更高,节约内存

总结:

  1. hashmap的数据结构包括了初始数组、链表、红黑树;
  2. 插入数据的时候使用pos = key % size 来进行插入数据;
  3. 当两个或者两个以上的key的相同就会发生冲突,就会挂在数组初始位置的链表后;
  4. 当某个节点后出现过多的链表节点的时候,就会转换成红黑树以提高效率。
  5. 数组容量2的倍数:
    1)提高运算速度;
    2)增加散列度,降低冲突;
    3)减少内存碎片。
  6. hash函数与pos定位:hashcode的高16位与低16位进行异或求模,增加了散列度,降低了冲突。
  7. 插入冲突:通过单链表解决冲突,如果链表长度超过(TREEIFY_THRESHOLD = 8),进行单链表和红黑树的转换以提高查询速度。
  8. 扩容:
    1)扩容的条件:实际节点数大于等于容量的四分之三;
    2)扩容后数据排布:要么是原下标的位置,要么是原下标 + 原容量的位置
  9. 序列化:只存储了数组的容量、实际节点数量和各个节点的key、value值。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值