I find a very magic thing, the simple code as below:
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");
}
}
after invoke
HashMap<String,String> map = new HashMap<String,String>();
the field variable entrySet is not null, that is to say it have been initialize.
Then this is my first question, when the entrySet has been initialized? it seemed the relevant code should be in the construct of HashMap, but below is the source code of this constructor
public HashMap() {
this.loadFactor = DEFAULT_LOAD_FACTOR; // all other fields defaulted
}
it seemed there dont exist code which initialize entrySet.
and thing go on. after invoke
map.put("a","aa")
the content of field variable table and entrySet as below shot. Then this is my second problem: when add this value into entrySet? It seemed that it should be the put method achieve these thing. and below is put method.
public V put(K key, V value) {
return putVal(hash(key), key, value, false, true);
}
it invoke putVal method and below is some code of 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;
}
after invoke
++modCount;
the entrySet is empty and before invoke
afterNodeInsertion(evict);
the entrySet has a element. but it seemed the code between these two line has nothing with entrySet. I think maybe there exist several threads operate entrySet then I write a small tool with jvm_ti to print the threadID which invoke the class below package java.util and find there is only one thread.
Then what I miss? Does there exist issue at process of debug? Wish I have describe my problem clearly and everything would be appreciate.
add: my java version is 1.8.0_77 and eclipse version is 4.6.1 and 4.5.1
HashMap entrySet() Method in Java util. HashMap. entrySet() method in Java is used to create a set out of the same elements contained in the hash map. It basically returns a set view of the hash map or we can create a new set and store the map elements into them.
put() method of HashMap is used to insert a mapping into a map. This means we can insert a specific key and the value it is mapping to into a particular map. If an existing key is passed then the previous value gets replaced by the new value. If a new pair is passed, then the pair gets inserted as a whole.
The Java HashMap entrySet() returns a set view of all the mappings (entries) present in the hashmap. Here, hashmap is an object of the HashMap class.
The Static Initializer for a Static HashMap We can also initialize the map using the double-brace syntax: Map<String, String> doubleBraceMap = new HashMap<String, String>() {{ put("key1", "value1"); put("key2", "value2"); }};
It is your debugger that fools you. The debugger view calls toString()
which in fact calls entrySet()
(see AbstractMap.toString()
). That is why the entrySet
was already initialized, when you looked at it.
If you look in there via reflection utils, e.g. with the following code:
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);
you get the following output:
entrySet = null
map.toString() = {}
entrySet = []
As you can see: entrySet in fact is still null
if no toString()
is called and gets initialized after it.
The same applies to your second question. If you look at the values "reflectively":
// Starting from where my entrySet is still null
map.put("key", "value");
entrySet = entrySetField.get(map);
System.out.println("entrySet = " + entrySet);
you get, as expected:
entrySet = null
Quick look into source code reveals that it is allocated lazily:
public Set<Map.Entry<K,V>> entrySet() {
Set<Map.Entry<K,V>> es;
return (es = entrySet) == null ? (entrySet = new EntrySet()) : es;
}
Reference
I think maybe there exist several threads operate entrySet then I write a small tool with jvm_ti to print the threadID which invoke the class below package java.util and find there is only one thread.
No, definitely there are NO
threads involved (unless you explicitly created them)
If you want to debug it easily, set watchpoint on
transient Set<Map.Entry<K,V>> entrySet;
inside HashMap.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With