1.put()方法:大方向上可以分为三块:1.初始化,2扩容,3数据迁移
public V put(K key, V value) {
return putVal(key, value, false);
}
/** Implementation for put and putIfAbsent */
final V putVal(K key, V value, boolean onlyIfAbsent) {
//key和value都不允许null
if (key == null || value == null) throw new NullPointerException();
int hash = spread(key.hashCode());
// 用于记录相应链表的长度
int binCount = 0;
//遍历数组
for (Node<K,V>[] tab = table;;) {
Node<K,V> f; int n, i, fh;
//数组不存在或者没数据的情况,初始化
if (tab == null || (n = tab.length) == 0)
tab = initTable();
//如果数组当前位置为null,用一次 CAS 操作将这个新值放入其中
else if ((f = tabAt(tab, i = (n - 1) & hash)) == null) {
if (casTabAt(tab, i, null,
new Node<K,V>(hash, key, value, null)))
break; // no lock when adding to empty bin
}
//
else if ((fh = f.hash) == MOVED)
tab = helpTransfer(tab, f);
else {
//如果f是头结点
V oldVal = null;
//加锁
synchronized (f) {
//
if (tabAt(tab, i) == f) {
//头结点的 hash 值大于 0,说明是链表
if (fh >= 0) {
//链表长度+1
binCount = 1;
//遍历链表
for (Node<K,V> e = f;; ++binCount) {
K ek;
if (e.hash == hash &&
((ek = e.key) == key ||
(ek != null && key.equals(ek)))) {
// 如果发现了"相等"的 key,判断是否要进行值覆盖
oldVal = e.val;
if (!onlyIfAbsent)
e.val = value;
break;
}
// 到了链表的最末端,将新值放到链表的最末端
Node<K,V> pred = e;
if ((e = e.next) == null) {
pred.next = new Node<K,V>(hash, key,
value, null);
break;
}
}
}
//如果是一个红黑树的结构,将新值放到红黑树中
else if (f instanceof TreeBin) {
Node<K,V> p;
binCount = 2;
if ((p = ((TreeBin<K,V>)f).putTreeVal(hash, key,
value)) != null) {
oldVal = p.val;
if (!onlyIfAbsent)
p.val = value;
}
}
}