HashMap源码分析(1.7版本)
HashMap 采用的数据结构 = 数组(主) + 单链表(副),该数据结构方式也称:拉链法
具体描述如下
HashMap数组
其核心为一个table[] (哈希数组),数组的下标为处理过的HashMap键的hash值,数组元素为一个键值对或者一个链表的头节点。数组的大小为HashMap的容量。
HashMap链表
- 每个链表=哈希表的桶(bucket)
- 链表的节点值=1个键值对
- 链表长度=桶的大小
?链表主要用于解决hash冲突:若不同key值计算出来的hash值相同(即都需存储到数组的同1个位置),由于之前该hash值的数组位置已存放好元素, 则将原先位置的元素移到单链表中,冲突hash值对应的键值对放入到数组元素(即发生冲突时,新元素插入到链表头仲:制元素总是添加到歌组中,旧元素移到单链表中) 该采用链表解决hash冲突的方法=链地址法
HashMap 的本质 = 1个存储Entry 类对象的数组 + 多个单链表Entry 对象本质 = 1个映射(键 - 值对),属性包括:键(key )、值(value ) & 下1节点( next ) = 单链表的指针 = 也是一个Entry 对象,用于解决hash 冲突
static class Entry<K,V> implements Map.Entry<K,V> {
final K key;
V value;
Entry<K,V> next;
int 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;
}
public final V setValue(V newValue) {
V oldValue = value;
value = newValue;
return oldValue;
}
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();
}
void recordAccess(HashMap<K,V> m) {
}
void recordRemoval(HashMap<K,V> m) {
}
}
V get(Object key);
V put(K key, V value);
void putAll(Map<? extends K, ? extends V> m);
V remove(Object key);
boolean containsKey(Object key);
boolean containsValue(Object value);
Set<K> keySet();
Collection<V> values();
void clear();
int size();
boolean isEmpty();
HashMap扩容机制
|