I know java Hashmap has a capacity and load factor parameter.So , if the number of items in this hashmap is more than capacity* load factor, a new hashmap will be reconstructed.I have some questions about the re-constructions of it:
- The previous hashmap will be reclaimed or still be in use if the reconstruction happened?
- since we need a larger size hashmap , so , will the hash function be changed ?
- For ConcurrentHashMap , what if one thread is inserting(Of cource, this insert operation has lead to a re-construction) and another thread is reading?For example, it will read from the old hashmap or from the new hashmap?
It's still the same hashmap, just the internal storage is reconstructed. After reconstruction the old bucket array is not needed anymore and could be gc'ed.
Update: Internally
HashMap
hasNode<K,V>[] table
. During resize a new array will be constructed, the elements are moved and thentable
is replaced with the new array. After that operation the map itself would not reference the old array anymore so unless there are no other references (which is unlikely due totable
being package private) it is elligible for gc.No, the hash function won't change. It generally doesn't depend on the number of buckets but the generated hash will be adjusted to get the correct bucket (e.g. by applying a modulo)
Update:
HashMap
calculates the bucket index like this:(size - 1) & hash
,hash
is the return value of the key'shashCode()
method, which doesn't depend on the map itself.I'd have to guess here (I'll look up the code later) but I assume as long as threads are reading from the old buckets they'll still be in use and will be freed later.
Update: I had a quick look at the
ConcurrentHashMap
sources and there are reference to the currenttable
which is used byget()
and a possiblenextTable
which is the target for resize operations. During resize the elements are transferred tonextTable
and at the endtable
is set tonextTable
, effectively switching tables.This means that during resizing the old table is still read and at some point it gets replaced. During insert operations there might be some blocking, e.g. by using synchronized blocks, especially if a resize is needed or already being performed.
The documentation also hints at this:
This means that
get
won't block butput
,remove
etc. might block at some point.