首页 > 编程知识 正文

HashMap的底层实现原理,hashmap转成红黑树

时间:2023-05-06 02:39:25 阅读:129426 作者:1482

最近研究了HaspMap的数据结构,然后将一系列问题整理如下:

对象存储在HashMap中的数组索引index如何计算? hashcode和hash的值有什么区别? 为什么HashMap的数组长度必须为2^n? 对比红黑树和AVL树的优劣吗? 在hashcode中判断为对象相等、在equals ()、"=="中判断的区别、与Integer联系的自动解吸箱和高速缓存,首先以排列链表方式存储HashMap的最旧的数据结构的存储从JDK8变更为数组链表红黑树的存储方式,链表长度超过阈值(8)时将链表转换为红黑树。 性能进一步提高了。

本节介绍HashMap如何计算对象的hashcode并将其放置在指定的数组索引中。 1、HashMap首先用key的hashcode ()计算hashcode (),是int型) 2、hashcode和hashcode的无符号右移16位进行异或运算,hash值staticfification 0:(h=key.hashcode () ) ) ) ) ) ) ) ); (对于无//符号的右移位和以下运算记忆,如果不熟悉,请参阅本人的位运算博客。 使用https://blog.csdn.net/CP PPP 66/article/details/115795107、hash值和length-1进行运算,求出存储时对应的数组索引index的length不排列有时也称为桶bucket的数量。 随之,为什么求索引要使用运算而不是模式mod运算呢? 传统的哈希表经常使用取模操作来计算哈希值,以确保对象可以全部散列分布在数组中。 但是,由于计算机的计算原理,运算速度大于mod运算。 但是需要注意的是!

amodb=a(B-1)成立的条件是b=2^n!

由此规定,HashMap的序列长度必须为2 ̄n

这应该可以解决关于HashMap数组长度必须为2^n的原因的问题。

在Java中,HashMap的结构具有参数InitialCapacity,默认值为16。 《阿里巴巴Java开发手册》中提到:

【推荐】Hashmap(intinitialcapacity )初始化时设定

initialCapacity=(需要保存的元素数/负载因子) 1。 请注意,加载因子(loader factor )默认为0.75。

如果没有初始值initialCapacity大小,则默认值为16。

这是因为,如果没有设置容量初始大小,随着元素的增加,容量将不得不扩大,resize需要重建散列表,从而严重影响性能。

在此resize时,将数组的长度设置为*2,然后重新计算每个对象的索引。 对性能有极大影响。

红黑树的介绍和AVL树的区别关于红黑树RB Tree :

红黑树是含有红黑节点的两股平衡搜索树。 必须满足以下性质:

性质1 )各节点为黑色或红色。 性质2 :根节点为黑色。 性质3 )各叶节点(NIL )为黑色(在Java中,叶节点为null节点)。 性质4 )每个红色节点的两个子节点一定是黑色的。 性质5 )从任意节点到叶节点的路径都包含相同数量的黑节点。 关于平衡二叉树:也称为AVL树,是各节点左右部分树的高度差在1以下的二叉树。 插入新节点或删除节点后,树不平衡时会旋转并再次平衡。 红黑树是在这个基础上发展起来的。

二叉排序树:也称为二进制搜索树二叉搜索树。 其性质是,任何节点的左部分树的节点值都比该右部分树的节点值小(如果部分树不为空)。 且不允许出现具有相等值的节点。

红黑树和AVL树的区别:

红黑树不追求“完全平衡”,只追求粗略平衡,以牺牲节点插入和删除的可维护性来换取高级平衡。 任何不平衡都将在三圈内解决。 因为AVL是严格的均衡树,所以在某些情况下删除或增加节点会比红黑树旋转次数多。

由于红黑树查询性能略微逊色于AVL树(但都是Olog(n))比AVL树稍不平衡,因此红黑树的查询性能最多只能比相同内容的AVL树比较一次。 但是,维护比AVL强,可以更快地恢复平衡。

使用hashcode判断对象相等,与使用equals ()、“==”的区别和联系: 1、hashcode与equals的关系: hashcode ) )在Object类中是公共IC

hashcode ) )根据类的不同,在改写后生成hashcode的规则也不同。

但是,一般来说有以下原则。

1 .如果两个对象equals返回true,则hashCode也必须返回相同的int数。

2 .两个对象equals返回false,但ha

shCode有小概率可能会相同,然而自己设计时建议为不相等的对象生成不同hashCode值这样可以提高哈希表的性能。
3.若两个对象hashCode返回相同int数,则equals不一定返回true。
4.若两个对象hashCode返回不同int数,则equals一定返回false。

所以当需要对比对象的时候;

首先用hashCode()去对比,如果hashCode()不一样,则表示这两个对象肯定不相等(也就是不必再用equal()去再对比了)如果hashCode()相同,此时再对比他们的equal(),如果equal()也相同,则表示这两个对象是真的相同了。

【强制】1、对于集合的处理:只要重写 equals(),就必须重写 hashCode()。
2、因为 Set 存储的是不重复的对象,依据 hashCode 和 equals 进行判断,所以 Set 存储的对象必须重写这两个方法。 ----《阿里巴巴Java开发手册》

equals()与 == 的区别

“==” 判断的是内存地址空间是否相同,仅适用于8大基本数据类型与本类型作比较。
尽管这8大基本类型的不同名变量的值相同,引用的却是常量池中同一值的地址。
所以可以用 “==” 来判断是否相等。

equals()判断的是封装类变量内值是否相等。
不同的封装类变量即使值相等,在堆中的内存地址也不同,所以不可以用 == 来判断。

这里再拓展一点为什么Interger与int做“==”比较可以返回true。

这里要首先知道Integer是int的包装类,是个引用类型并且类里面有很多方法可以使用。

但是当Integer与int做“==”比较的时候,其实是Integer自动拆箱(unboxing)变成了int,然后再去做比较。两个相同值的int做“==”比较当然结果是true囖。

而关于自动装箱:

Integer i=6; //实际执行的是 Integer i=Integer.valueOf(6);给i传的是个int值,却变成了Integer对象,这就称之为自动装箱boxing

还要拓展关于Interger缓存的小点:

Integer a = 127;Integer b = 127;System.out.println(a == b);//trueInteger c = 128;Integer d = 128;System.out.println(c == d);//false

[-128,127]是Integer的缓存范围。当实例化了一值处于缓存范围内的对象时,会在栈内存常量池中创建这一值,当再次有Integer使用常量池中具有的值来实例化对象时,会直接指向此常量地址空间。所以出现了"=="判断为true的情况

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