gpt4 book ai didi

java - HashMap 如何以及何时初始化 EntrySet 并向其中添加值

转载 作者:行者123 更新时间:2023-12-02 08:00:17 24 4
gpt4 key购买 nike

我发现一个很神奇的东西,简单的代码如下:

public class Demo{
public static void main(String[] args){
HashMap<String,String> map = new HashMap<String,String>();
map.put("a", "aa");
System.out.println("end");
}
}

调用后

HashMap<String,String> map = new HashMap<String,String>();

the state of map object字段变量entrySet不为null,即已初始化。

<小时/>

那么这是我的第一问题,entrySet何时初始化?看起来相关代码应该在HashMap的构造中,但下面是这个构造函数的源代码

 public HashMap() {
this.loadFactor = DEFAULT_LOAD_FACTOR; // all other fields defaulted
}

似乎不存在初始化entrySet的代码。

事情还在继续。调用后

map.put("a","aa")

字段变量tableentrySet的内容如下图。 enter image description here那么这是我的第二个问题:什么时候将这个值添加到entrySet中?看起来应该是 put 方法实现这些东西。下面是 put 方法。

public V put(K key, V value) {
return putVal(hash(key), key, value, false, true);
}

它调用putVal方法,下面是putVal的一些代码

final V putVal(...) {
....
tab[i] = newNode(hash, key, value, null);
....
++modCount;//after invoke this the entrySet is still empty
if (++size > threshold)
resize();//this has not been executed
afterNodeInsertion(evict);//I debug several times, sometimes before invoke this the entrySet has an Element and sometimes
return null;
}

调用后

 ++modCount;

entrySet 为空在调用之前

 afterNodeInsertion(evict);

entrySet 有一个元素。但这两行之间的代码似乎与entrySet无关。我想可能存在多个线程操作entrySet,然后我用jvm_ti编写一个小工具来打印线程ID,该线程ID调用包java.util下面的类> 发现只有一个线程。

那我想念什么呢?调试过程中是否存在问题?希望我能清楚地描述我的问题,一切都会很感激。

添加:我的java版本是1.8.0_77,eclipse版本是4.6.14.5.1>

最佳答案

是你的调试器欺骗了你。调试器 View 调用 toString(),它实际上调用 entrySet()(请参阅 AbstractMap.toString())。这就是为什么当您查看时 entrySet 已经初始化了。

如果您通过反射实用程序查看那里,例如使用以下代码:

HashMap<String, String> map = new HashMap<>();

Field entrySetField = HashMap.class.getDeclaredField("entrySet");
entrySetField.setAccessible(true);
Object entrySet = entrySetField.get(map);
System.out.println("entrySet = " + entrySet);
System.out.println("map.toString() = " + map.toString());
entrySet = entrySetField.get(map);
System.out.println("entrySet = " + entrySet);

您将得到以下输出:

entrySet = null
map.toString() = {}
entrySet = []

如您所见:如果没有调用 toString() 并在其之后进行初始化,entrySet 实际上仍然是 null

这同样适用于你的第二个问题。如果您“反射(reflection)性地”查看这些值:

// Starting from where my entrySet is still null
map.put("key", "value");
entrySet = entrySetField.get(map);
System.out.println("entrySet = " + entrySet);

正如预期的那样,你会得到:

entrySet = null

关于java - HashMap 如何以及何时初始化 EntrySet 并向其中添加值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41714233/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com