- 结构、null键null值
HashMap是基于Hash表对Map接口的实现,HashMap具有较快的访问速度,但是遍历的顺序却是不确定的,HashMap提供所有可选的映射操作,并允许使用null键和null值。
- 线程不安全
HashMap并非线程安全,当存在多个线程同时写入HashMap时,可能会导致数据不一致。
- 字段
loadFactor 称为负载因子,默认值为0.75
threshold 表示所能容纳键值对的临界值
threshold = 数组长度 * 负载因子
size 是HashMap中实际存在的键值对的数量
modCount字段用来记录HashMap内部发生结构变化的次数
HashMap的默认容量为INITIAL_CAPACITY=16
- 存储结构
HashMap 采用数组+链表+红黑树的内部存储结构
HashMap的数组部分称为Hash桶,当链表的长度大于等于8时,链表将以红黑树的结构进行存储,当长度降到6是,转成链表
链表的时间复杂度O(N)
红黑树的时间复杂度O(logN)
- Node 节点
每个Node节点存储着用来定位数据索引位置的Hash值,K键,V值以及指向链表下一节点的指针组成
Node是HashMap的内部类,实现了Map.Entry接口,本质是一个键值对
static class Node<K, V> implements Map.Entry<K, V> {
final int hash;
final K key;
V value;
Node<K, V> next;
}
- 确定Node存储位置
当向HashMap中插入数据时,首先要确定在hash桶数组中的位置
static final int hash(Object key) {
int h;
return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);
}
以添加key键为字符 'e' 为例 HashMap首先调用hashCode()方法,获取键的hashCode值h(101),然后对其进行高位运算:
将h右移16位以取得h的高16位,与原h的低16位进行异或运算(结果为101),最后将得到的h值与(table.length - 1)进行与运算获得该对象的保留位以计算下标。