hashmap的实现原理数组entry
HashMap在⽇常⼯作中使⽤场景⾮常多,程序员都知道是HashMap是线程⾮安全的,但是底层是以什么⽅式存储的?本⼈仔细研读了⼀下源码,也只是掌握了核⼼的存储功能,并没有把全部代码看明⽩,但是对于理解hashMap的存储结构完全够了。
存储结构
1. hashmap底层是以数组⽅式进⾏存储。将key-value对作为数组中的⼀个元素进⾏存储。
2. key-value都是Map.Entry中的属性。其中将key的值进⾏hash之后进⾏存储,即每⼀个key都是计算hash值,然后再存储。每⼀个
Hash值对应⼀个数组下标,数组下标是根据hash值和数组长度计算得来。
3. 由于不能的key有可能hash值相同,即该位置的数组中的元素出现两个,对于这种情况,hashmap采⽤链表形式进⾏存储。
4. 下图描述了hashmap的存储结构图
黄影Entry结构分析
1. Entry是hashMap中封装key-value键值对的,主要包括如下属性
1 2 3 4 5 6 7 8 9 10static class Entry<K,V> implements Map.Entry<K,V> {
final K key;// map中key值,可以为null。
V value; // map中的value值,可以为null。
Entry<K,V> next;// 链表引⽤,防⽌key值不同,hash值相同。
int hash; // 每个key的hash值
// 构造函数
Entry(int h, K k, V v, Entry<K,V> n) {
value = v;
next = n;
key = k;
hash = h;
}
public final K getKey() {
return key;
}
public final V getValue() {
return value;
}
// 同⼀个key时,新值替换旧值,返回旧值
public final V tValue(V newValue) {
V oldValue = value;
value = newValue;
return oldValue;24小时值班制度
}
/
/ key值重写equals⽅法
public final boolean equals(Object o) {
if (!(o instanceof Map.Entry))
return fal;
Map.Entry e = (Map.Entry)o;
Object k1 = getKey();
Object k2 = e.getKey();
if (k1 == k2 || (k1 != null && k1.equals(k2))) {
Object v1 = getValue();
Object v2 = e.getValue();
if (v1 == v2 || (v1 != null && v1.equals(v2)))
return true;
}
return fal;
}
// 重写hashCode值
public final int hashCode() {
return Objects.hashCode(getKey()) ^ Objects.hashCode(getValue()); }
public final String toString() {
return getKey() + "=" + getValue();
}
// 其他⽅法省略
}
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
43
44
45
46
47
48
49
50
51
HashMap属性分析1. HashMap的属性分析
1 2 3 4 5 6public class HashMap<K,V>
extends AbstractMap<K,V>
implements Map<K,V>, Cloneable, Serializable
{
/**
*默认情况下,hashmap⼤⼩为16.即1<<4就是1乘以2的4次幂=16
*/
static final int DEFAULT_INITIAL_CAPACITY = 1 << 4; // aka 16
/**
* hashMap的最⼤值
适合发朋友圈的话*/
static final int MAXIMUM_CAPACITY = 1 << 30;
/
**
* 默认加载加载因⼦,即使⽤空间达到总空间的0.75时,需要扩容。
*/
static final float DEFAULT_LOAD_FACTOR = 0.75f;
/**
* 声明hashmap⼀个空数组。
*/
static final Entry<?,?>[] EMPTY_TABLE = {};
/**
* 最开始时,hashmap是⼀个空数组。
*/
transient Entry<K,V>[] table = (Entry<K,V>[]) EMPTY_TABLE;
/**
* map的元素的个数
*/
transient int size;
/*
* hashmap的实际存储空间⼤⼩。这个空间是总空间*加载因⼦得出的⼤⼩。
* ⽐如默认是16,加载因⼦是0.74。则threshold就是12。
*/
int threshold;
/**
* 加载因⼦,即使⽤空间达到总空间的0.75时,需要扩容。
*/
final float loadFactor;
/**
*
*/
transient int modCount;
/**
* threshold这个值的最⼤值就是Integer.MAX_VALUE
*/
static final int ALTERNATIVE_HASHING_THRESHOLD_DEFAULT = Integer.MAX_VALUE;
7
8
9
10
桑竹11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
itunes下载安装31
qq可以群发吗
32
33
认知策略34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
put⽅法
1. put(key,value)⽅法是hashmap中最重要的⽅法,使⽤hashmap最主要的就是使⽤put,get两个⽅法。put⽅法底层存储⼜是什么
呢,我们可以从put⽅法的源码进⾏分析