HashMap1.8hash collision and expansion method

Why learn hashMap source
because the collection in our work and the learning process is very common, and the code is written in a very elegant, if you want to get a job as a high-wage, and now the city
jdk1.8 surface has been popular up, I believe the interview process, the interviewer will ask for more and more knowledge of the source code, the source code is all we have to understand
, the next question we have to learn conceived before the source of the source hashMap1.8 together
for thought
1. hashMap initialization size is the number
2. hashMap structure is what
3. If you have a data structure that is hashMap chain plus an array, then how are we going to avoid hash collisions
4. hashMap at what time expansion
the expansion approach is what
the official papers
hashMap structure
1 in 1.8, hashMap 'configuration into arrays and array plus chain + red-black tree, because of the consideration of 1.8 without the index list, the low efficiency of traversing
the next, so when the chain length is greater than 8--1 i.e. 7:00, will be converted into red-black tree, then when the length is less than 6, and will be converted into a red-black tree in the list
like the data structure describing the source is transi ent Node <K, V> [ ] table; and is a single node list object, the structure is an array list +  
 

[Java]  plain text view  Copy the code
?
1
2
static final int TREEIFY_THRESHOLD = 8; 树的临界点
static final int UNTREEIFY_THRESHOLD = 6;非树的临界点


hash collision
1. Now that we know the structure of hashMap, then the next, we will look at how he placed hash collision issue, in accordance with our vision, I
can let it to the modulo length of the array, such as array length is 16, we can use the hash value of the key modulo the array, to take positive values are 0-15
good location can fall on the array, but this does not guarantee that the digital much as possible the dispersion falls array , while too much falls on the same node elements
will lead to the formation of the length of the list is too long, and affecting the value of speed hashmap, so we now look at how the source code is implemented

[Java]  plain text view  Copy the code
?
01
02
03
04
05
06
07
08
09
10
public V put(K key, V value) {
return putVal(hash(key), key, value, false, true);
}
static final int hash(Object key) {
int h;
return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);
} i
f ((p = tab[i = (n - 1) & hash]) == null)
tab[i] = newNode(hash, key, value, null);
static final int DEFAULT_INITIAL_CAPACITY = 1 << 4; // aka 16


Taken together, this method two parameters involved in the calculation
option1: hash value
option2: length of the array is -1 then the length of the array, and the comment in the source has been pointed out, the length of the array needs to be 2 ^ n-th power, i.e., the even
an int hash values, we can assume a random:
010101010101001010101010101010
it with an even number or a non-even-operation & take what would be the result?
If an odd number is taken and the result obtained, i.e., & may be an odd number, it may be an even number, and an even if only the answer is a & even number,
so the answer is obvious, only when the length of the array is an even number n, i.e., 2 when the power at this time in order to ensure that the resulting figures may be even that is likely to be an odd number
that we'll look at the first value, the first value is a hash value, the hash value calculation only and length - 1 array, then if hash value is assumed to take direct and
array calculations, corresponding to the hash value only a few involved in the operation, and the other bits not involved in the operation, this may also be different elements that give
the same result (i.e., equal to the last few but the first few different), the approaches used in the source code is the hash value to the right 16 to give him the upper 16
bits and lower 16 bits while taking XOR, so that we can ensure that the entire hash values are involved operation, and that the divergence or why it? Such as exclusive or may obtained
0,1 possible average binary
Example
0 1 0 1
0 1 0 1 & take
probability of 00 010 0.75 1 0.25
0. 11 0
0 1 0 1 takes |
0 1 1 1 probability 0 0.25 1 0.75
. 1 0 1 0
0 1 0 1 takes ^
0 1 1 0 probability of a probability. 1 0.5 0.5
the hash expansion process
in the expansion process 1.8 hashMap resize is determined by the method of
this method serves two purposes
1. Initialization
2. Expansion

[Java]  plain text view  Copy the code
?
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
{
for (int j = 0; j < oldCap; ++j) {
Node<K,V> e;
if ((e = oldTab[j]) != null) {
oldTab[j] = null;
if (e.next == null)
newTab[e.hash & (newCap - 1)] = e;
else if (e instanceof TreeNode)
((TreeNode<K,V>)e).split(this, newTab, j, oldCap);
else { // preserve order
Node<K,V> loHead = null, loTail = null;
Node<K,V> hiHead = null, hiTail = null;
Node<K,V> next;
do {
next = e.next;
if ((e.hash & oldCap) == 0) {
if (loTail == null)
loHead = e;
else
loTail.next = e;
loTail = e;
} e
lse {
if (hiTail == null)
hiHead = e;
else
hiTail.next = e;
hiTail = e;
}
} while ((e = next) != null);
if (loTail != null) {
loTail.next = null;
newTab[j] = loHead;
} i
f (hiTail != null) {
hiTail.next = null;
newTab[j + oldCap] = hiHead;
}
}
}
}
}


This method is to determine the expansion of the core code
is first traverse the array, traversal three paragraphs of the logic
1 if element on the array is null, and if a null, then the tail-interpolation (1.7 is used in the first interpolation method, but the head inserted in a multithreaded situation may
die circular list appears here not long on interpretation)
2. If the red-black tree is then processed in handling red-black tree
3. If the array elements, according to our ideas, we should the key is to recalculate the position in the array of
core code: is e.hash & oldCap
we found that when it is calculated, it does not calculate direct and oldCap -1 & instead and length of the array is calculated directly
then we again this calculation into the way look at this sophisticated algorithm how it is:
when you first expansion, resize method of execution

[Java]  plain text view  Copy the code
?
1
2
3
4
5
6
7
8
9
if (oldCap > 0) {
if (oldCap >= MAXIMUM_CAPACITY) {
threshold = Integer.MAX_VALUE;
return oldTab;
} e
lse if ((newCap = oldCap << 1) < MAXIMUM_CAPACITY &&
oldCap >= DEFAULT_INITIAL_CAPACITY)
newThr = oldThr << 1; // double threshold
}


此时数组的长度已经扩大了两倍
新长度是32 ,老长度是16
0101010101010010101010101 0 1 0 1 0
0 1 1 1 1 老长度-1 //1
1 0 0 0 0 老长度 //2
0 1 1 1 1 1 新长度-1 //3
用 1,3对比,我们可以发现,数组移动不移动是看第五位是否是0 ,如果是0 ,不移动,如果不是0 ,新长度的值要
比原来的值 大16
用2,3 对比,如果第五5位是0,那么得到的结果就是0 ,如果第五位非0 ,那么得到的结果就不是0
1,3移动---> 第五位非0 ,且移动16 位 ---> 第五位 0 , 不移动
2,3 ---> 第五位非0 ,知道要移动了,且在源码中可以发现,移动了16
第五位 0 ,不移动

[Java] 纯文本查看 复制代码
?
1
2
3
4
if (hiTail != null) {
hiTail.next = null;
newTab[j + oldCap] = hiHead;
}


所以移动不移动,只需要看倒数第五位即可,不得不说,hashMap这个设计很精妙
结束语
相信通过刚才的学习,同学们已经对hash的碰撞问题和hash的扩容方法有了一个具体的认识,希望大家继续认真
学习。

发布了966 篇原创文章 · 获赞 11 · 访问量 3万+

Guess you like

Origin blog.csdn.net/xiaoyaGrace/article/details/105270495