1.类的定义

public class HashMap<K,V>
extends AbstractMap<K,V>
implements Map<K,V>, Cloneable, Serializable

2.基本成员变量

1.默认初始化容量 16

static final int DEFAULT_INITIAL_CAPACITY = 1 << 4;

2.最大容量

static final int MAXIMUM_CAPACITY = 1 << 30;

3.默认加载因子

static final float DEFAULT_LOAD_FACTOR = 0.75f;

4.空表

static final Entry<?,?>[] EMPTY_TABLE = {};

5.存储数据的数组

transient Entry<K,V>[] table = (Entry<K,V>[]) EMPTY_TABLE;

6.已使用容量大小

transient int size;

7.阀值,当越过后会进行扩容

int threshold;

8.加载因子

final float loadFactor;

9.修改的次数统计

transient int modCount;

10.HashMap的默认阀值

static final int ALTERNATIVE_HASHING_THRESHOLD_DEFAULT = Integer.MAX_VALUE;

11.随机化的hash值

transient int hashSeed = 0;

3.构造方法

1.有参(initialCapacity, loadFactor)

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;
threshold = initialCapacity;
init();
}

2.有参(initialCapacity)

public HashMap(int initialCapacity) {
this(initialCapacity, DEFAULT_LOAD_FACTOR);
}

当只传入大小的时候直接传入大小和默认加载因子
3.无参

public HashMap() {
this(DEFAULT_INITIAL_CAPACITY, DEFAULT_LOAD_FACTOR);
}

当调用无参构造的时候直接传入默认大小,和默认加载因子即可
4.有参(Map)

public HashMap(Map<? extends K, ? extends V> m) {
this(Math.max((int) (m.size() / DEFAULT_LOAD_FACTOR) + 1,
DEFAULT_INITIAL_CAPACITY), DEFAULT_LOAD_FACTOR);
inflateTable(threshold);
putAllForCreate(m);
}

4.roundUpToPowerOf2

private static int roundUpToPowerOf2(int number) {
// assert number >= 0 : "number must be non-negative";
return number >= MAXIMUM_CAPACITY
? MAXIMUM_CAPACITY
: (number > 1) ? Integer.highestOneBit((number - 1) << 1) : 1;
}

返回最接近number的2的幂的数

5.inflateTable

private void inflateTable(int toSize) {
// Find a power of 2 >= toSize
int capacity = roundUpToPowerOf2(toSize);

threshold = (int) Math.min(capacity * loadFactor, MAXIMUM_CAPACITY + 1);
table = new Entry[capacity];
initHashSeedAsNeeded(capacity);
}

扩展HashMap

6.init

void init() {
}

空方法

7.initHashSeedAsNeeded

final boolean initHashSeedAsNeeded(int capacity) {
boolean currentAltHashing = hashSeed != 0;
boolean useAltHashing = sun.misc.VM.isBooted() &&
(capacity >= Holder.ALTERNATIVE_HASHING_THRESHOLD);
boolean switching = currentAltHashing ^ useAltHashing;
if (switching) {
hashSeed = useAltHashing
? sun.misc.Hashing.randomHashSeed(this)
: 0;
}
return switching;
}

初始化哈希掩码值

8.hash

final int hash(Object k) {
//默认掩码
int h = hashSeed;
if (0 != h && k instanceof String) {
return sun.misc.Hashing.stringHash32((String) k);
}
//减少hash冲突
h ^= k.hashCode();
h ^= (h >>> 20) ^ (h >>> 12);
return h ^ (h >>> 7) ^ (h >>> 4);
}

求得一个对象的hash

9.indexFor

static int indexFor(int h, int length) {
// assert Integer.bitCount(length) == 1 : "length must be a non-zero power of 2";
return h & (length-1);
}

找到要找到对象在数组的那个位置当一个数&2的幂次-1的时候就会产生一个[0,2^n-1]的范围的数

10.size

public int size() {
return size;
}

返回当前 已用长度

11.isEmpty

public boolean isEmpty() {
return size == 0;
}

判断当前HashMap是否为空

12.get

public V get(Object key) {
//如果key为null调用一个单独的方法,说明HashMap支持键为null
if (key == null)
return getForNullKey();
//先获取到Entry实体
Entry<K,V> entry = getEntry(key);
//返回值
return null == entry ? null : entry.getValue();
}

通过键取值

13.getForNullKey

private V getForNullKey() {
if (size == 0) {
return null;
}
//注意:null键所对应的实体在table[0]存储
for (Entry<K,V> e = table[0]; e != null; e = e.next) {
if (e.key == null)
return e.value;
}
return null;
}

获取到键为null的所对应的值

14.containsKey

public boolean containsKey(Object key) {
//直接调用getEntry看能不能找到对应的Entry实体即可
return getEntry(key) != null;
}

判断键是否存在

15.getEntry

final Entry<K,V> getEntry(Object key) {
//size=0说明整个HashMap中无元素直接返回null
if (size == 0) {
return null;
}
//先获取到键的hash当键为null的时候为0
int hash = (key == null) ? 0 : hash(key);
//通过indexFor方法传入hash和数组长度获取到当前key应该在数组的那个下标处,然后遍历此下标的链表
for (Entry<K,V> e = table[indexFor(hash, table.length)];
e != null;
e = e.next) {
Object k;
//匹配成功即返回
if (e.hash == hash &&
((k = e.key) == key || (key != null && key.equals(k))))
return e;
}
return null;
}

通过Key获取到Entry实体

16.put

public V put(K key, V value) {
//如果为空表,则需要初始化
if (table == EMPTY_TABLE) {
inflateTable(threshold);
}
//如果key为null的话调用特殊方法进行处理
if (key == null)
return putForNullKey(value);
//获得当前key的hash值
int hash = hash(key);
//获得其应该存放在数组中的位置
int i = indexFor(hash, table.length);
//遍历此位置
for (Entry<K,V> e = table[i]; e != null; e = e.next) {
Object k;
//如果找到相同的key,则覆盖掉原来的值,并且返回oldValue
if (e.hash == hash && ((k = e.key) == key || key.equals(k))) {
V oldValue = e.value;
e.value = value;
e.recordAccess(this);
return oldValue;
}
}
//如果没有找到重复的值
modCount++;
//直接将新值添加到table[i]的后面
addEntry(hash, key, value, i);
return null;
}

将一组值放入HashMap

17.putForNullKey

private V putForNullKey(V value) {
//可以看出和put原理差不多只不过其遍历的只是table[0]的位置
for (Entry<K,V> e = table[0]; e != null; e = e.next) {
if (e.key == null) {
V oldValue = e.value;
e.value = value;
e.recordAccess(this);
return oldValue;
}
}
modCount++;
addEntry(0, null, value, 0);
return null;
}

当key为null的时候将值放入到table[0]号位置

18.putForCreate

private void putForCreate(K key, V value) {
int hash = null == key ? 0 : hash(key);
int i = indexFor(hash, table.length);

/**
* Look for preexisting entry for key. This will never happen for
* clone or deserialize. It will only happen for construction if the
* input Map is a sorted map whose ordering is inconsistent w/ equals.
*/
for (Entry<K,V> e = table[i]; e != null; e = e.next) {
Object k;
if (e.hash == hash &&
((k = e.key) == key || (key != null && key.equals(k)))) {
e.value = value;
return;
}
}
createEntry(hash, key, value, i);
}

他被putAllForCreate调用然后被构造方法调用

19.putAllForCreate

private void putAllForCreate(Map<? extends K, ? extends V> m) {
for (Map.Entry<? extends K, ? extends V> e : m.entrySet())
putForCreate(e.getKey(), e.getValue());
}

直接遍历即可,在HashMap构造的参数为Map的时候调用

20.resize

void resize(int newCapacity) {
Entry[] oldTable = table;
int oldCapacity = oldTable.length;
if (oldCapacity == MAXIMUM_CAPACITY) {
threshold = Integer.MAX_VALUE;
return;
}
//新的数组
Entry[] newTable = new Entry[newCapacity];
//将原数组复制,获取到新的hash掩码然后重新哈希
transfer(newTable, initHashSeedAsNeeded(newCapacity));
//切换table
table = newTable;
//更改阀值
threshold = (int)Math.min(newCapacity * loadFactor, MAXIMUM_CAPACITY + 1);
}

扩容

21.transfer

void transfer(Entry[] newTable, boolean rehash) {
int newCapacity = newTable.length;
编译以前的table
for (Entry<K,V> e : table) {
//将所有节点挪动
while(null != e) {
Entry<K,V> next = e.next;
//判断是否需要重新哈希
if (rehash) {
e.hash = null == e.key ? 0 : hash(e.key);
}
int i = indexFor(e.hash, newCapacity);
e.next = newTable[i];
newTable[i] = e;
e = next;
}
}
}

替换数组

22.putAll(Map)

public void putAll(Map<? extends K, ? extends V> m) {
int numKeysToBeAdded = m.size();
if (numKeysToBeAdded == 0)
return;
if (table == EMPTY_TABLE) {
inflateTable((int) Math.max(numKeysToBeAdded * loadFactor, threshold));
}
//判断是否需要扩容当大于阀值就需要扩容
if (numKeysToBeAdded > threshold) {
int targetCapacity = (int)(numKeysToBeAdded / loadFactor + 1);
if (targetCapacity > MAXIMUM_CAPACITY)
targetCapacity = MAXIMUM_CAPACITY;
int newCapacity = table.length;
while (newCapacity < targetCapacity)
newCapacity <<= 1;
if (newCapacity > table.length)
resize(newCapacity);
}
//直接循环put
for (Map.Entry<? extends K, ? extends V> e : m.entrySet())
put(e.getKey(), e.getValue());
}

将一个Map放入

23.remove(key)

public V remove(Object key) {
Entry<K,V> e = removeEntryForKey(key);
return (e == null ? null : e.value);
}

通过key删除数据并且返回以前的值

24.removeEntryForKey

final Entry<K,V> removeEntryForKey(Object key) {
if (size == 0) {
return null;
}
//先找到节点的位置
int hash = (key == null) ? 0 : hash(key);
int i = indexFor(hash, table.length);
Entry<K,V> prev = table[i];
Entry<K,V> e = prev;

while (e != null) {
Entry<K,V> next = e.next;
Object k;
if (e.hash == hash &&
((k = e.key) == key || (key != null && key.equals(k)))) {
modCount++;
size--;
//如果要删除的节点是第一个只需要将第二个放入数组中就可以
if (prev == e)
table[i] = next;
else
//如果不是就需要将前一个节点的next置于next
prev.next = next;
e.recordRemoval(this);
return e;
}
prev = e;
e = next;
}

return e;
}

通过key删除一个元素

25.removeMapping

final Entry<K,V> removeMapping(Object o) {
//可以看出其参数必须为Map的Entry
if (size == 0 || !(o instanceof Map.Entry))
return null;

Map.Entry<K,V> entry = (Map.Entry<K,V>) o;
Object key = entry.getKey();
int hash = (key == null) ? 0 : hash(key);
int i = indexFor(hash, table.length);
Entry<K,V> prev = table[i];
Entry<K,V> e = prev;

while (e != null) {
Entry<K,V> next = e.next;
if (e.hash == hash && e.equals(entry)) {
modCount++;
size--;
if (prev == e)
table[i] = next;
else
prev.next = next;
e.recordRemoval(this);
return e;
}
prev = e;
e = next;
}

return e;
}

删除一个entry节点

26.clear

public void clear() {
modCount++;
Arrays.fill(table, null);
size = 0;
}

直接将数组中的所有东西变为null即可

27.containsValue

public boolean containsValue(Object value) {
//特殊情况
if (value == null)
return containsNullValue();
//直接两层for循环遍历
Entry[] tab = table;
for (int i = 0; i < tab.length ; i++)
for (Entry e = tab[i] ; e != null ; e = e.next)
if (value.equals(e.value))
return true;
return false;
}

查看有没有某个值

28.containsNullValue

private boolean containsNullValue() {
Entry[] tab = table;
for (int i = 0; i < tab.length ; i++)
for (Entry e = tab[i] ; e != null ; e = e.next)
if (e.value == null)
return true;
return false;
}

查找是否为值为null的value

29.clone

public Object clone() {
HashMap<K,V> result = null;
try {
result = (HashMap<K,V>)super.clone();
} catch (CloneNotSupportedException e) {
// assert false;
}
if (result.table != EMPTY_TABLE) {
result.inflateTable(Math.min(
(int) Math.min(
size * Math.min(1 / loadFactor, 4.0f),
// we have limits...
HashMap.MAXIMUM_CAPACITY),
table.length));
}
result.entrySet = null;
result.modCount = 0;
result.size = 0;
result.init();
result.putAllForCreate(this);
return result;
}

可以看出其直接构造了一个新的HashMap并且调用putAllForCreate直接将原HashMap的值全部放进去

30.Entry类

static class Entry<K,V> implements Map.Entry<K,V> {
//键
final K key;
//值
V value;
//下一个节点
Entry<K,V> next;
//hash值
int hash;

/**
* Creates new entry.
*/
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;
}

public final V setValue(V newValue) {
V oldValue = value;
value = newValue;
return oldValue;
}
//equals的关键在于比key和value
public final boolean equals(Object o) {
if (!(o instanceof Map.Entry))
return false;
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 false;
}

public final int hashCode() {
return Objects.hashCode(getKey()) ^ Objects.hashCode(getValue());
}

public final String toString() {
return getKey() + "=" + getValue();
}

/**
* This method is invoked whenever the value in an entry is
* overwritten by an invocation of put(k,v) for a key k that's already
* in the HashMap.
*/
void recordAccess(HashMap<K,V> m) {
}

/**
* This method is invoked whenever the entry is
* removed from the table.
*/
void recordRemoval(HashMap<K,V> m) {
}
}

31.addEntry

void addEntry(int hash, K key, V value, int bucketIndex) {
if ((size >= threshold) && (null != table[bucketIndex])) {
//可以看出当容量不足的时候为2倍扩容
resize(2 * table.length);
hash = (null != key) ? hash(key) : 0;
bucketIndex = indexFor(hash, table.length);
}
createEntry(hash, key, value, bucketIndex);
}

添加节点

32.createEntry

void createEntry(int hash, K key, V value, int bucketIndex) {
//先获取到原来这个位置的entry
Entry<K,V> e = table[bucketIndex];
//创建一个新的节点放到这个位置并且将其next置为e
table[bucketIndex] = new Entry<>(hash, key, value, e);
size++;
}

创建一个新节点