首页 > 编程知识 正文

HashMap数据结构,hashtable底层数据结构

时间:2023-05-03 11:18:06 阅读:129413 作者:4723

首先看源代码:

说明位移运算。

14是位移运算表现,是十进制16

1的二进制表示: 1

移动左4位后的二进制表示为b(10000 )=d (16 )

更简单的计算方法是1 n相当于12的n次幂

进入正题

HashMap的基础数据结构为数组+链表,JDK1.8还引入了红黑树。 如果链表长度超过8个,则将链表转换为红黑树以提高搜索性能。

HashMap有两个参数:初始容量和加载系数。

1、HashMap初始容量为哈希表中桶的数量,初始容量仅为创建哈希表时的容量。

2、HashMap的加载因子加载因子是哈希表在自动扩展容量之前可以达到多少容量的度量。

3、如果作用哈希表中的条目数超过加载因子与当前容量的乘积,则扩展该哈希表,进行rehash操作,即重建内部数据结构。 扩展后的哈希表容量将是原来的两倍。

为了降低碰撞概率,rehash是一个非常耗时的操作,因为当HashMap数组的长度达到阈值时,将开始扩展并将所有元素rehash重新定位到扩展的容器中。

此阈值由加载系数和当前容器的容量确定。

efault _ initial _ capacity * default _ load _ factor

也就是说,默认情况下,如果16x0.75=12,将触发扩展操作。

/* * * implements map.putandrelatedmethods.* * @ paramhashhhashforkey * @ paramkeythekey * @ paramvaluethevaluetoput * @ par don ' tchangeexistingvalue * @ paramevictiffalse,thetableisincreationmode.* @ returnpreviousvalue ornullifnone */finalvpupure NodeK,V p; int n,I; if () tab=table )==null||(n=tab.Length )=0) n=(tab=resize ) ).length; if () p=tab(I=(n-1 ) hash]] ) null (tab ) I )=new node (hash,key,value,null ); else { NodeK,V e; k; if(p.hash==hash ) (k=p.key )==key||(key!=nullkey.equals(k ) ) (e=p; elseif(pinstanceoftreenode ) e=(treenodek,v ) p ).puttreeval ) this,tab,hash,key,value ); else{for(intbincount=0; binCount () if ) (e=p.next ) null ) ) p.next=newnode ) hash,key,value,null ); if (bincount=tree ify _ threshold-1 )/-1for1STTreeifybin(tab,hash ); 布雷克; (if ) e.hash==hash((k=e.key )==key||(key!=nullkey.equals(k ) ) (break; p=e; }if(e!=null (//existingmappingforkeyvoldvalue=e.value; if (! olyifabsent|||old value==null (e.value=value; afternodeaccess(e; 返回载荷值; } }模具计数; 大小阈值(if )大小); 自动识别(evict; 返回空值; (4、面试高频度)为什么加载因子的初始化是0.75呢? 总的来说,如果太小(如0.5 ),则即使HashMap每put的数据量很少,也需要进行一次容量扩展,容量扩展操作将极大地消耗性能。 在降低空间利用率的同时,增加了“重建内部数据结构”操作的次数。 如果太大,例如即使设定为1,容量也仍然为16,假设当前数组中占用15个,如果再put数据并计算数组索引,则发生hash碰撞的概率为15/16,hashmm 这还减少了空间开销,提高了空间利用率,但也增加了查询时间的成本。 因此,选择0.75作为默认加载因子是一种在时间和空间成本上寻求折中的选择。 为了最大限度地减少刷新操作的次数,必须考虑映射所需的条目数及其加载系数来设置初始容量。 因此,通常建议在使用HashMap时根据估计值设置初始容量,以减少扩展操作。 4、面试高频:为什么初始容量为16容量为2的乘方时,源代码中n -1对应的二进制数都为1,这样可以保证与key的hashcode运算后均匀分布,这样可以减少hash冲突的次数默认值为16而不是2、4、8,32、64、1024等应该是折中处理,太小则不能容纳某些元素,需要扩展容量,而扩展容量是消耗性能的操作。 取太多的值会浪费更多的内存空间。 因此,在日常开发中,如果HashMap可以估计节点上存储的数量,则必须在初始化时指定容量。

参考原文:

HashMap容量和负载因子: https://blog.csdn.net/ye 17186/article/details/88876417

HashMap的初始容量和加载因子: https://blog.csdn.net/weixin _ 44723496/article/details/112387738

版权声明:该文观点仅代表作者本人。处理文章:请发送邮件至 三1五14八八95#扣扣.com 举报,一经查实,本站将立刻删除。