首页 > 编程知识 正文

hashtable底层数据结构,静态内部类和内部类的区别

时间:2023-05-04 04:47:28 阅读:129414 作者:1592

1、HashMap数据结构

jdk8之前的数据结构是数组链表

jdk8以后的数据结构是数组链表的红黑树

并发时,如果发生扩展,可能会发生循环链表,在get运行过程中接触死循环,引起CPU 100%的问题,因此必须避免在并发环境中使用HashMap

2、HashMap为什么选择数组链表中红黑树的数据结构

序列:保存和获取效率最高,时间复杂度为o(1)

链表:要解决混列冲突问题,必须遍历链表中的所有数据。 时间的复杂性是o(n )

红色树:优化链表性能,使搜索、插入、删除等操作时间的复杂性达到o(logn )

3、为什么不用红黑树直接用链表达到指定长度时转换为红黑树?

元素数量少,红黑树与链表相比效率低,红黑树失去平衡,需要自旋(左旋、右旋)才能维持树的自身平衡

4、链表转移到红黑树的阈值来源和链表转移到红黑树的条件

阈值来源:

统计链表转换为红黑树的阈值,概率分布(概率统计)为(一个元素、两个元素、三个元素)的列表出现的概率

转换条件:

仅当数组长度大于或等于64且数组元素链表长度大于或等于9时转换

5、为什么序列长度达到64才可能转化为红黑树?

finalvoidtreeifybin(node[]tab,int hash ) {

int n,index; 节点e;

//todo数组的长度小于64时,不会转换为红黑树

if(tab==null||(n=tab.Length ) MIN_TREEIFY_CAPACITY () ) ) ) ) ) 0

resize (;

elseif () e=tab [索引=(n-1 ) hash]!=空) {

TreeNode hd=null,tl=null;

do {

treenode p=替换趋势(e,null );

if(TL==null ) )。

高清=p;

else {

p.prev=tl;

tl.next=p;

}

tl=p;

}while((e=e.next )!=null;

if () tab[index]=HD高清)!=null )

高清.三叉树(tab;

}

}

复制代码

6、为什么链表中转红黑树的阈值不是8而是9?

finalvputval(inthash,K key,V value,布尔在线,

布尔事件) {

节点[ ]选项卡; 节点p; int n,I;

//todo初始化大小(扩展操作)

(if () tab=table )==null|| (n=tab.length (==0) ) ) ) ) ) ) )

n=(tab=resize () ).length;

//todo通过混列计算判断对应的数组元素是否有值

if () p=tab(I=(n-1 ) hash] )==null ) )

如果没有//todo,则直接插入元素

tab[I]=newnode(hash,key,value,null );

else {

//todo到此为止,请注意与该散列值对应的数组元素中已经有元素

节点e; k;

//todo判断key是否存在,如果存在则覆盖旧的值

if(p.hash==hash

() k=p.key )==key|(key!=nullkey.equals(k ) )

e=p;

//todo判断是否是红黑树

elseif(pinstanceoftreenode ) )。

e=() treenode ) p ).puttreeval ) this,tab,hash,key,value );

//todo进入链表逻辑

else {

for(intbincount=0; binCount ) {

if () e=p.next )==null ) {

创建//todonode节点

p.next=newnode(hash、key、value、null );

//7以上,循环8次,创建8个节点,加上以前存在的1个节点,直到链表长度为9,才变换红黑树

if (bincount=tree ify _ threshold-1 )//-1 for 1st

treeifybin(tab,hash );

布雷克;

}

if(e.hash==hash

() k=e.key )==key|(key!=nullkey.equals(k ) )

布雷克;

p=e;

}

}

if(e!=null(//existingmappingforkey

V oldValue=e.value;

if (! onlyIfAbsent || oldValue==null )

e .值=值;

afternodeaccess(e;

返回载荷值;

}

}

模具计数;

大小阈值(if ) )。

resize (;

自动识别(evict;

返回空值;

}

复制代码

7、为什么HashMap建议序列容量为2的指数次方

容量初始化:

输入容量将转换为最接近此数且大于此数的2的指数次幂,而不是2的指数次幂

为了提高效率,混码%长度的取模效率过低,位运算混码(长度-1)效率高,JDK版本1.7的序列扩展会产生大量的混码

8、为什么负荷因子为0.75?

为了解决hash冲突问题

负载因子为1或更大时,碰撞的可能性更高,链表的长度越长,查找时间的复杂性越高(

负载率小于等于0.5时,查询快,空间切换时间短,混列冲突低

0.75这个数值被牛顿二项式推翻,在时间和空间上进行折中处理

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