基础知识
数据结构基础
- 数组:连续的内存块,不支持动态扩容,查询简单,直接通过下标即可获取对应元素【寻址容易,插入和删除困难】;
- 链表:非连续内存块,可动态扩容,但是不能通过下标查询【寻址困难,插入和删除容易】;
散列表:数组里保存的元素是链表,也叫哈希表,具体是通过Hash算法将数据内容和数据地址进行映射对应
HashMap继承图
什么是Hash
一种将数据内容和数据地址对应起来的算法;
- 把任意长度的内容通过Hash算法转化为统一长度的输出;
- 可以通过输入值唯一确定一个HashCode,但是不能通过HashCode唯一确定输入值,因为输入值的长度远远大于输出值,所以必然会有不同的输入值产生同一个输出值的情况;
-
HashMap数据结构
Hash碰撞
树化
当散列表中的链表长度超过了8【这个值是固定的 -> TREEIFY_THRESHOLD】或者数组的长度大于64,HashMap将会对链表内容进行树化,将链表数据结构转化为红黑树;
路由算法
( table.length - 1) & node.length
源码分析
基础参数
static final int DEFAULT_INITIAL_CAPACITY = 1 << 4; // HashMap初始化容量大小,值为16
static final int MAXIMUM_CAPACITY = 1 << 30; // HashMap最大容量为32,是int的最大正值
static final float DEFAULT_LOAD_FACTOR = 0.75f; // HashMap负载因子
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;
构造方法
```java 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); // 无论传入的是什么数值,返回一个比这个数值大的2的次方数 }
public HashMap(int initialCapacity) { this(initialCapacity, DEFAULT_LOAD_FACTOR); }
public HashMap() { this.loadFactor = DEFAULT_LOAD_FACTOR; // all other fields defaulted }
public HashMap(Map<? extends K, ? extends V> m) { this.loadFactor = DEFAULT_LOAD_FACTOR; putMapEntries(m, false); }
<a name="0owdI"></a>
#### Node/TreeNode
<a name="c8rrj"></a>
#### tableSizeFor
```java
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;
}