HashMap底层实现采用了哈希表,这是一种非常重要的数据结构。
哈希表的基本数据结构式就是数组加链表
数据结构中有数组和链表来实现对数据的存储,他们又各种特点。
1、数组:占用空间连续,寻址容易,查询速度快。但是增加和删除效率非常低。
2、链表:占用空间不连续。寻址困难,查询速度慢。但是增加和删除效率非常高。
需要找到一种结合查询快且增删效率高的数据结构,那就是哈希表。
核心源码
1、Node
该表在首次使用时初始化,并根据需要调整大小。 分配时,长度始终是2的幂次方。 (在某些操作中,我们还允许长度为零,以允许使用当前不需要的引导机制。)
Node是一个单向链表。
transient Node<K,V>[] table;
static class Node<K,V> implements Map.Entry<K,V> {
final int hash;
final K key;
V value;
Node<K,V> next;
Node(int hash, K key, V value, Node<K,V> next) {
this.hash = hash;
this.key = key;
this.value = value;
this.next = next;
}
public final K getKey() { return key; }
public final V getValue() { return value; }
public final String toString() { return key + "=" + value; }
public final int hashCode() {
return Objects.hashCode(key) ^ Objects.hashCode(value);
}
public final V setValue(V newValue) {
V oldValue = value;
value = newValue;
return oldValue;
}
public final boolean equals(Object o) {
if (o == this)
return true;
if (o instanceof Map.Entry) {
Map.Entry<?,?> e = (Map.Entry<?,?>)o;
if (Objects.equals(key, e.getKey()) &&
Objects.equals(value, e.getValue()))
return true;
}
return false;
}
}
@HotSpotIntrinsicCandidate
public native int hashCode();
Integer中对hashCode做重写
@Override
public int hashCode() {
return Integer.hashCode(value);
}
数组长度必须为2的整数幂,这样采用位运算即可实现取余的效果: hash值 = hascode&(数组长度-1)。、
插入算法:当添加一个元素(key-value)时,首先计算key的hash值,以此确定插入数组中的位置,但是可能存在同一个hash值的元素已经被存放在数组同一位置了,这时就添加到同一个hash值的元素后面,他们在数组同一位置,就形成了链表,同一个链表上的Hash值是相同的,所以说数组存放是链表。当链表长度大于8时,链表就转换为红黑树,这样又大大提高了查找的效率。
HashSet: 底层使用hashMap实现的,没有顺序不可重复