首页 > 编程知识 正文

hashtable有序还是无序,树的遍历和二叉树的遍历区别

时间:2023-05-06 21:03:45 阅读:30026 作者:2169

混叠贴图遍历元素的顺序。

第一,HashMap元素的基本存储顺序

我们知道HashMap是“无序的”,即插入顺序没有保证。 但是,HashMap其实也是有序的,同一key-value对的组在扫描时顺序一致,不管他们插入的顺序是什么。

照片是从简单的本APP发给你的

上面的代码分别用两种方法插入。 也就是说,虽然插入顺序不同,但遍历的结果相同。 这样可以理解,只要你插入这19个元素,对于HashMap存储,都是按照相同的顺序存储的。

这个实际上也很容易理解。 由于HashMap使用hash算法确定key的逻辑存储位置,因此如果key相同,则逻辑存储位置也相同。

遍历的结果如下。

11=11

12=12

13=13

14=14

15=15

16=16

17=17

18=18

19=19

0=0

1=1

2=2

3=3

4=4

5=5

6=6

7=7

8=8

9=9

十=十

为什么是这个顺序呢? 本人非常不理解。

如果是基于key的hashcode定位逻辑存储,那么关键的key的hashcode也不支持。 key的hashcode打印如下。

1568

1569

1570

1571

1572

1573

1574

1575

1576

49

50

51

52

53

54

55

56

57

1567

混列映射使用混列算法将key映射到table数组所在的位置。 在本例中,HashMap的初始化容量指定为20,最终HashMap将容量转换为32。 这个HashMap的数组是长32的数组。

(为什么? 稍后说明)

是的,有32个长度的数组。 然后插入第一个元素,即key为0的字符串。 这个key的hashcode值是48。 那么,这个key映射到数组的哪个位置呢? 这个key对应于数组的下标吗?

这里有个需要注意的问题。 长度为32的数组下标必然从0变为31。 然后,该数组的遍历顺序也按照从0到31的顺序开始遍历。

通过查看源代码,我们发现数组的下标不是key的hashcode值,而是key的hashcode值通过位和逻辑运算得到的。

让我们先看看源代码。 其他代码不在这里贴。 我们只看最下面一行最重要的代码。 下图所示。

照片是从简单的本APP发给你的

newtab[e.hash(newcap-1 ) ]=e;

就是这个代码。 这个代码将新节点Node放在数组中,然后放在数组的哪个位置呢?

在下标=e.hash(newcap-1 )的位置!

现在,我们打印e.hash(NewCap-1 ),看看到底是什么。

因为我们有20个元素,所以HashMap最终扩展后的大小是32。 也就是说,情况如下。

newCap=32

e. hash正如我刚才说的,是key的hashcode值。 好吧,打印出来看看是什么鬼东西。

0-1-2-3-4-5-6-7-8-16-17-18-19-20-21-22-23-24-25-31

这就是结果!

这就是HashMap元素的保存顺序!

这就是HashMap元素的基础逻辑地址!

这个! 我的疑惑终于解开了!

让我们考虑以下两个重要问题。

1、指定的size大小为20,容量大小为什么为32?

2,HashMap为什么不直接使用key的hashcode值定位数组下标呢?

第二个问题是HashMap的容量扩展问题

如果在初始化HashMap时未指定,则默认容量大小为16。 源代码如下所示。

默认_ initial _ capacity=14

但是把容量指定为20,为什么变成32呢?

要弄清楚这个问题,必须弄清楚HashMap容量大小的计算逻辑。

源代码如下:

照片是从简单的本APP发给你的

该方法是一系列逻辑位运算。 反正现在不知道,但没关系。 把代码拿来,跑着看结果。

进入16岁的时候,回到16岁。

准入20的时候,返回是32。

原来如此,HashMap的容量大小必须是2的n次方。

结论HashMap的容量应为2的n次幂。 如果给定的整数s不是2的n次方,HashMap内部将其转换为大于s的2的n次方的整数。

当然,这个整数是大于s的2的n次方的整数中最小的。

三、HashMap为什么不直接用key的hashcode值定位数组下标?

理由很简单。 此示例中的HashMap数组是一个长度为32的数组,下标从0到31。

如果key的hashcode值超过31,就不行了。

因此,java的开发者将key的hashcode值映射到了0到31的区间范围。 你是怎么映射的? 上面列举了:

e.hash(NewCap-1 ) ) )。

将key的hashcode值和31操作为位。

java的位置和操作,忘记的事情可以自己用大脑来弥补。 这里不说明。 网上有很多说明。 在此阐述java设计者实现的思路。 为什么要这样实施?

为什么呢? 因为HashMap是可扩展的,所以名为newCap的变量是动态的。 在这个例子中是32,但是64会怎么样呢? 如果是256呢?

此时,我将此newCap作为变量接受用户输入。 现在,key的hashcode值已成功映射到指定范围的区间:

【0至newCap负1】

这里的位和操作是重要的,并且如果想要将随机整数映射到指定范围的区间,则可以考虑使用位和操作。 这是计算机逻辑运算的特性,java的开发人员很好地利用了这个特性。

那么,今天的共享到此结束。

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