相关疑难解决方法(0)

HashMap调整方法实现细节

正如标题所示,这是一个关于实现细节的问题HashMap#resize- 当内部数组的大小加倍时.这有点罗嗦,但我真的试图证明我对此有了最好的理解......

这发生在这个特定桶/箱中的条目以某种方式存储的时刻Linked- 因此具有确切的顺序并且在问题的上下文中这是重要的.

一般来说,resize也可以从其他地方调用,但我们只看这个案例.

假设你将这些字符串作为键放在一个HashMap(右边是hashcode 后面 HashMap#hash - 那是内部重新散列.)是的,这些都是精心生成的,而不是随机的.

 DFHXR - 11111
 YSXFJ - 01111 
 TUDDY - 11111 
 AXVUH - 01111 
 RUTWZ - 11111
 DEDUC - 01111
 WFCVW - 11111
 ZETCU - 01111
 GCVUR - 11111 
Run Code Online (Sandbox Code Playgroud)

这里有一个简单的模式 - 最后4位对于所有这些都是相同的 - 这意味着当我们插入这些键中的8个(总共9个)时,它们最终会在同一个桶中; 并在9个HashMap#put时,resize将被调用.

因此,如果当前有8个条目(上面有一个键)HashMap- 这意味着在这个映射中有16个桶,它们的最后4个位决定了条目最终的位置.

我们把第九个键.此时TREEIFY_THRESHOLD被击中并被resize召唤.这些容器加倍,32并且键的另一位决定了该条目的位置(因此,现在为5位).

最终到达这段代码(当resize发生时):

 Node<K,V> loHead = null, loTail = null;
 Node<K,V> …
Run Code Online (Sandbox Code Playgroud)

java hashmap hashcode java-8

19
推荐指数
1
解决办法
1494
查看次数

关于不可变集和映射的JDK9随机化

阅读这个问题Eugene给出的答案,我发现JDK9不可变集和映射将引入一个随机性源,它将影响它们的遍历.这意味着迭代顺序确实是随机的,至少在JVM的不同运行中是这样.

由于规范不保证集合和映射的任何遍历/迭代顺序,这绝对没问题.实际上,代码绝不能依赖于特定于实现的细节,而是依赖于规范.

我知道今天,使用JDK 8,如果我有一个HashSet并且这样做(取自链接的答案):

Set<String> wordSet = new HashSet<>(Arrays.asList("just", "a", "test"));

System.out.println(wordSet);

for (int i = 0; i < 100; i++) {
    wordSet.add("" + i);
}

for (int i = 0; i < 100; i++) {
    wordSet.remove("" + i);
}

System.out.println(wordSet);
Run Code Online (Sandbox Code Playgroud)

然后元素的迭代顺序将改变,两个输出将不同.这是因为向集合中添加和删除100个元素会更改HashSet和重新构造元素的内部容量.这是完全有效的行为.我这里不是在问这个问题.

但是,使用JDK9,如果我这样做:

Set<String> set = Set.of("just", "a", "test");
System.out.println(set);
Run Code Online (Sandbox Code Playgroud)

然后,在JVM的另一个实例中,我运行相同的代码,输出可能不同,因为已经引入了随机化.

到目前为止,我在youtube上发现了这个优秀的视频(分钟44:55),其中Stuart Marks说这种随机化的一个动机是:

(...)人们编写的应用程序无意中依赖于迭代顺序.(...)所以,无论如何,迭代顺序是一个大问题,我认为有很多代码存在潜在的依赖于迭代顺序尚未发现的代码.(......)所以,我们对此的回应是故意在随机迭代顺序Set,并Map在新的集合.因此,在集合的迭代顺序不可预测但稳定之前,这些是可预测的不可预测的.因此,每次JVM启动时,我们都会获得一个随机数,并将其作为种子值使用,并与哈希值混合使用.因此,如果你运行一个初始化一个集合然后以任何顺序打印出元素的程序,你会得到一个答案,然后,如果再次调用JVM并运行相同的程序,那么元素集通常会出现在不同的顺序.所以,这里的想法是(...)如果你的代码中存在迭代顺序依赖,过去曾经发生的事情是,新的JDK版本出来了,你测试你的代码和(...)它' d需要数小时的调试才能将其追溯到迭代顺序中的某种变化.这意味着该代码中存在一个依赖于迭代顺序的错误.现在,如果你更频繁地改变迭代次序,比如每次JVM调用,那么(我们希望)奇怪的行为会更频繁地表现出来,事实上我们希望你在做测试时......

因此,动机很明确,而且很明显,这种随机化只会影响新的不可变集和映射.

我的问题是:这种随机化还有其他动机吗?它有什么优势?

java random collections maps java-9

12
推荐指数
2
解决办法
490
查看次数

标签 统计

java ×2

collections ×1

hashcode ×1

hashmap ×1

java-8 ×1

java-9 ×1

maps ×1

random ×1