目录
默认参数及构造方法put()方法resize()扩容方法get()方法remove()方法replace()方法
看源码之前首先要知道HashMap底层存储结构
默认参数及构造方法
static final int DEFAULT_INITIAL_CAPACITY
= 1 << 4;
static final int MAXIMUM_CAPACITY
= 1 << 30;
static final float DEFAULT_LOAD_FACTOR
= 0.75f;
static final int TREEIFY_THRESHOLD
= 8;
static final int UNTREEIFY_THRESHOLD
= 6;
static final int MIN_TREEIFY_CAPACITY
= 64;
transient Node
<K,V>[] table
;
transient Set
<Map
.Entry
<K,V>> entrySet
;
transient int size
;
transient int modCount
;
int threshold
;
final float loadFactor
;
static final int tableSizeFor(int cap
) {
int n
= cap
- 1;
n
|= n
>>> 1;
n
|= n
>>> 2;
n
|= n
>>> 4;
n
|= n
>>> 8;
n
|= n
>>> 16;
return (n
< 0) ? 1 : (n
>= MAXIMUM_CAPACITY
) ? MAXIMUM_CAPACITY
: n
+ 1;
}
public HashMap(int initialCapacity
, float loadFactor
) {
if (initialCapacity
< 0)
throw new IllegalArgumentException("Illegal initial capacity: " +initialCapacity
);
if (initialCapacity
> MAXIMUM_CAPACITY
)
initialCapacity
= MAXIMUM_CAPACITY
;
if (loadFactor
<= 0 || Float
.isNaN(loadFactor
))
throw new IllegalArgumentException("Illegal load factor: " + loadFactor
);
this.loadFactor
= loadFactor
;
this.threshold
= tableSizeFor(initialCapacity
);
}
public HashMap(int initialCapacity
) {
this(initialCapacity
, DEFAULT_LOAD_FACTOR
);
}
public HashMap() {
this.loadFactor
= DEFAULT_LOAD_FACTOR
;
}
public HashMap(Map
<? extends K, ? extends V> m
) {
this.loadFactor
= DEFAULT_LOAD_FACTOR
;
putMapEntries(m
, false);
}
map-put过程形象图
put()方法
static final int hash(Object key
) {
int h
;
return (key
== null
) ? 0 : (h
= key
.hashCode()) ^ (h
>>> 16);
}
public V
put(K key
, V value
) {
return putVal(hash(key
), key
, value
, false, true);
}
final V
putVal(int hash
, K key
, V value
, boolean onlyIfAbsent
,boolean evict
) {
Node
<K,V>[] tab
;
Node
<K,V> p
;
int n
, i
;
if ((tab
= table
) == null
|| (n
= tab
.length
) == 0)
n
= (tab
= resize()).length
;
if ((p
= tab
[i
= (n
- 1) & hash
]) == null
)
tab
[i
] = newNode(hash
, key
, value
, null
);
else {
Node
<K,V> e
; K k
;
if (p
.hash
== hash
&&((k
= p
.key
) == key
|| (key
!= null
&& key
.equals(k
))))
e
= p
;
else if (p
instanceof TreeNode)
e
= ((TreeNode
<K,V>)p
).putTreeVal(this, tab
, hash
, key
, value
);
else {
for (int binCount
= 0; ; ++binCount
) {
if ((e
= p
.next
) == null
) {
p
.next
= newNode(hash
, key
, value
, null
);
if (binCount
>= TREEIFY_THRESHOLD
- 1)
treeifyBin(tab
, hash
);
break;
}
if (e
.hash
== hash
&&((k
= e
.key
) == key
|| (key
!= null
&& key
.equals(k
))))
break;
p
= e
;
}
}
if (e
!= null
) {
V oldValue
= e
.value
;
if (!onlyIfAbsent
|| oldValue
== null
)
e
.value
= value
;
afterNodeAccess(e
);
return oldValue
;
}
}
++modCount
;
if (++size
> threshold
)
resize();
afterNodeInsertion(evict
);
return null
;
}
扩容-链表处理
resize()扩容方法
final Node
<K,V>[] resize() {
Node
<K,V>[] oldTab
= table
;
int oldCap
= (oldTab
== null
) ? 0 : oldTab
.length
;
int oldThr
= threshold
;
int newCap
, newThr
= 0;
if (oldCap
> 0) {
if (oldCap
>= MAXIMUM_CAPACITY
) {
threshold
= Integer
.MAX_VALUE
;
return oldTab
;
}
else if ((newCap
= oldCap
<< 1) < MAXIMUM_CAPACITY
&& oldCap
>= DEFAULT_INITIAL_CAPACITY
)
newThr
= oldThr
<< 1;
}
else if (oldThr
> 0)
newCap
= oldThr
;
else {
newCap
= DEFAULT_INITIAL_CAPACITY
;
newThr
= (int)(DEFAULT_LOAD_FACTOR
* DEFAULT_INITIAL_CAPACITY
);
}
if (newThr
== 0) {
float ft
= (float)newCap
* loadFactor
;
newThr
= (newCap
< MAXIMUM_CAPACITY
&& ft
< (float)MAXIMUM_CAPACITY
?
(int)ft
: Integer
.MAX_VALUE
);
}
threshold
= newThr
;
@SuppressWarnings({"rawtypes","unchecked"})
Node
<K,V>[] newTab
= (Node
<K,V>[])new Node[newCap
];
table
= newTab
;
if (oldTab
!= null
) {
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 {
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
;
}
else {
if (hiTail
== null
)
hiHead
= e
;
else
hiTail
.next
= e
;
hiTail
= e
;
}
} while ((e
= next
) != null
);
if (loTail
!= null
) {
loTail
.next
= null
;
newTab
[j
] = loHead
;
}
if (hiTail
!= null
) {
hiTail
.next
= null
;
newTab
[j
+ oldCap
] = hiHead
;
}
}
}
}
}
return newTab
;
}
get()方法
public V
get(Object key
) {
Node
<K,V> e
;
return (e
= getNode(hash(key
), key
)) == null
? null
: e
.value
;
}
final Node
<K,V> getNode(int hash
, Object key
) {
Node
<K,V>[] tab
;
Node
<K,V> first
, e
;
int n
; K k
;
if ((tab
= table
) != null
&& (n
= tab
.length
) > 0 &&
(first
= tab
[(n
- 1) & hash
]) != null
) {
if (first
.hash
== hash
&&
((k
= first
.key
) == key
|| (key
!= null
&& key
.equals(k
))))
return first
;
if ((e
= first
.next
) != null
) {
if (first
instanceof TreeNode)
return ((TreeNode
<K,V>)first
).getTreeNode(hash
, key
);
do {
if (e
.hash
== hash
&&((k
= e
.key
) == key
|| (key
!= null
&& key
.equals(k
))))
return e
;
} while ((e
= e
.next
) != null
);
}
}
return null
;
}
remove()方法
public V
remove(Object key
) {
Node
<K,V> e
;
return (e
= removeNode(hash(key
), key
, null
, false, true)) == null
?
null
: e
.value
;
}
final Node
<K,V> removeNode(int hash
, Object key
, Object value
, boolean matchValue
, boolean movable
) {
Node
<K,V>[] tab
;
Node
<K,V> p
;
int n
, index
;
if ((tab
= table
) != null
&& (n
= tab
.length
) > 0 &&
(p
= tab
[index
= (n
- 1) & hash
]) != null
) {
Node
<K,V> node
= null
, e
; K k
; V v
;
if (p
.hash
== hash
&&((k
= p
.key
) == key
|| (key
!= null
&& key
.equals(k
))))
node
= p
;
else if ((e
= p
.next
) != null
) {
if (p
instanceof TreeNode)
node
= ((TreeNode
<K,V>)p
).getTreeNode(hash
, key
);
else {
do {
if (e
.hash
== hash
&&
((k
= e
.key
) == key
||
(key
!= null
&& key
.equals(k
)))) {
node
= e
;
break;
}
p
= e
;
} while ((e
= e
.next
) != null
);
}
}
if (node
!= null
&& (!matchValue
|| (v
= node
.value
) == value
||
(value
!= null
&& value
.equals(v
)))) {
if (node
instanceof TreeNode)
((TreeNode
<K,V>)node
).removeTreeNode(this, tab
, movable
);
else if (node
== p
)
tab
[index
] = node
.next
;
else
p
.next
= node
.next
;
++modCount
;
--size
;
afterNodeRemoval(node
);
return node
;
}
}
return null
;
}
@Override
public boolean remove(Object key
, Object value
) {
return removeNode(hash(key
), key
, value
, true, true) != null
;
}
replace()方法
@Override
public boolean replace(K key
, V oldValue
, V newValue
) {
Node
<K,V> e
; V v
;
if ((e
= getNode(hash(key
), key
)) != null
&&
((v
= e
.value
) == oldValue
|| (v
!= null
&& v
.equals(oldValue
)))) {
e
.value
= newValue
;
afterNodeAccess(e
);
return true;
}
return false;
}
@Override
public V
replace(K key
, V value
) {
Node
<K,V> e
;
if ((e
= getNode(hash(key
), key
)) != null
) {
V oldValue
= e
.value
;
e
.value
= value
;
afterNodeAccess(e
);
return oldValue
;
}
return null
;
}
转载请注明原文地址:https://ipadbbs.8miu.com/read-66082.html