上篇文章(http://www.itdecent.cn/p/a122c79ee60c)
我們分析了HashMap的構(gòu)造和put方法,這篇文章來看看它的其他方法
putAll
@Override
public void putAll(Map<? extends K, ? extends V> map) {
ensureCapacity(map.size());
super.putAll(map);
}
我們來看看 ensureCapacity(map.size());方法
private void ensureCapacity(int numMappings) {
int newCapacity = Collections.roundUpToPowerOfTwo(capacityForInitSize(numMappings));
HashMapEntry<K, V>[] oldTable = table;
int oldCapacity = oldTable.length;
if (newCapacity <= oldCapacity) {
return;
}
if (newCapacity == oldCapacity * 2) {
doubleCapacity();
return;
}
// We're growing by at least 4x, rehash in the obvious way
HashMapEntry<K, V>[] newTable = makeTable(newCapacity);
if (size != 0) {
int newMask = newCapacity - 1;
for (int i = 0; i < oldCapacity; i++) {
for (HashMapEntry<K, V> e = oldTable[i]; e != null;) {
HashMapEntry<K, V> oldNext = e.next;
int newIndex = e.hash & newMask;
HashMapEntry<K, V> newNext = newTable[newIndex];
newTable[newIndex] = e;
e.next = newNext;
e = oldNext;
}
}
}
}
首先得到一個(gè)新的容量newCapacity,如果等于舊容量的2倍就調(diào)用doubleCapacity()方法,這個(gè)方法在上一篇已經(jīng)解析過了,這邊就不再說了,makeTable方法創(chuàng)建一個(gè)新的數(shù)組,上篇文章也解析過了,下面著重看看這個(gè)循環(huán)
if (size != 0) {
int newMask = newCapacity - 1;
for (int i = 0; i < oldCapacity; i++) {
for (HashMapEntry<K, V> e = oldTable[i]; e != null;) {
HashMapEntry<K, V> oldNext = e.next;
int newIndex = e.hash & newMask;
HashMapEntry<K, V> newNext = newTable[newIndex];
newTable[newIndex] = e;
e.next = newNext;
e = oldNext;
}
}
}
首先計(jì)算出數(shù)據(jù)在新的數(shù)組當(dāng)中的index下標(biāo),如果next有數(shù)據(jù)又改變了鏈表的順利,總之就是把舊數(shù)組當(dāng)中的數(shù)據(jù)添加到了新的數(shù)組當(dāng)中,然后調(diào)用父類的putAll方法
public void putAll(Map<? extends K, ? extends V> map) {
for (Map.Entry<? extends K, ? extends V> entry : map.entrySet()) {
put(entry.getKey(), entry.getValue());
}
}
首先遍歷map對(duì)象參數(shù),然后調(diào)用HashMap的put方法添加數(shù)據(jù)。
get方法
public V get(Object key) {
if (key == null) {
HashMapEntry<K, V> e = entryForNullKey;
return e == null ? null : e.value;
}
int hash = Collections.secondaryHash(key);
HashMapEntry<K, V>[] tab = table;
for (HashMapEntry<K, V> e = tab[hash & (tab.length - 1)];
e != null; e = e.next) {
K eKey = e.key;
if (eKey == key || (e.hash == hash && key.equals(eKey))) {
return e.value;
}
}
return null;
}
如果key==null,就返回entryForNullKey對(duì)象,不為null,首先計(jì)算hash值,然后計(jì)算index下標(biāo),得到對(duì)象
如果eKey == key || (e.hash == hash && key.equals(eKey)) 條件成立,就返回value。
remove方法
@Override
public V remove(Object key) {
if (key == null) {
return removeNullKey();
}
int hash = Collections.secondaryHash(key);
HashMapEntry<K, V>[] tab = table;
int index = hash & (tab.length - 1);
for (HashMapEntry<K, V> e = tab[index], prev = null;
e != null; prev = e, e = e.next) {
if (e.hash == hash && key.equals(e.key)) {
if (prev == null) {
tab[index] = e.next;
} else {
prev.next = e.next;
}
modCount++;
size--;
postRemove(e);
return e.value;
}
}
return null;
}
如果key為null,調(diào)用removeNullKey方法
private V removeNullKey() {
HashMapEntry<K, V> e = entryForNullKey;
if (e == null) {
return null;
}
entryForNullKey = null;
modCount++;
size--;
postRemove(e);
return e.value;
}
設(shè)置entryForNullKey對(duì)象為null。
key不為空
int hash = Collections.secondaryHash(key);
HashMapEntry<K, V>[] tab = table;
int index = hash & (tab.length - 1);
for (HashMapEntry<K, V> e = tab[index], prev = null;
e != null; prev = e, e = e.next) {
if (e.hash == hash && key.equals(e.key)) {
if (prev == null) {
tab[index] = e.next;
} else {
prev.next = e.next;
}
modCount++;
size--;
postRemove(e);
return e.value;
}
}
首先得到index,然后循環(huán)
如果刪除的數(shù)據(jù)在index位置,就把index位置的對(duì)象的下一個(gè)對(duì)象賦值給數(shù)組的index位置。
如果刪除的數(shù)據(jù)在index位置的鏈表中間就把鏈表中間的這個(gè)數(shù)據(jù)刪除掉,然后把中間數(shù)據(jù)的頭和尾連接在一起。
結(jié)束語
到此HashMap的常用方法都分析完了,通過看源碼對(duì)HashMap有了更深的理解。