本文作者:王一飞,叩丁狼高级讲师。原创文章,转载请注明出处。
上几篇讨论了并发环境下list容器的操作, 本篇我们来聊下另外一个集合容器:Map
Map:以key-value对的形式存在,一种数据结构,一个key, 映射一个value值, map中不能包含重复的key值, 一个key最多只能映射到一个值。
常用方法有:
添加: V put(K key, V value);
删除: V remove(Object key);
修改: V put(K key, V value);
查询: V get(Object key);
常见的实现类:
HashMap
LinkedHashMap
TreeMap
Hashtable
ConcurrentHashMap
要研究HashMap在并发环境下使用, 先得了解hashmap实现原理.HashMap是基于哈希表的 Map 接口的实现。(传送门:哈希表百度百科),其底层维护一个数组与链表.源码说话:
注意:
jdk8以前hashMap结构: 数组 + 链表
jdk8以后hashMap结构: 数组 + 链表 + 红黑树
此处源码使用的jdk8
源码:
public class HashMap<K,V> extends AbstractMap<K,V>
implements Map<K,V>, Cloneable, Serializable {
//初始容量, 默认16,俗称桶, 可以认为数组长度
//一个桶对应一条链表
static final int DEFAULT_INITIAL_CAPACITY = 1 << 4; // aka 16
//默认负载因子
static final float DEFAULT_LOAD_FACTOR = 0.75f;
//真实的负载因子, 不特意指定是等于0.75f;
final float loadFactor;
//阈值:所能容纳kv对最大数量,超过这个值,则需扩容
//规则: threshold = capacity * loadFactor
int threshold;
//哈希表, 如果必要, 长度以2的n次方方式拓展
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;
}
}
HashMap运作规则:
1>HashMap 初始化时(不特意指定), 默认创建长度为16的一维数组, 用于保存Node(即kv对)/挂载链表投节点
public HashMap() {
this.loadFactor = DEFAULT_LOAD_FACTOR;
}
2>map添加元素时map.put(key, value), 先通过哈希算法h = hash(key)计算出当前Node(key, value)在table数组中位置, 如果table[h]位置为null.table[h] = Node(key, valu