/**
删除过期的条目
@param 已经知道的有null key位置的位置
@return 已经知道的null key位置的下一个null(可存储位置)位置
**/
private int expungeStaleEntry(int staleSlot) {
Entry[] tab = table;
int len = tab.length;
// 删除过期条目
tab[staleSlot].value = null;
tab[staleSlot] = null;
size--;
// Rehash 直到碰到null
Entry e;
int i;
//从下一条目开始循环验证后面条目
for (i = nextIndex(staleSlot, len); (e = tab[i]) != null; i = nextIndex(i, len)) {
ThreadLocal k = e.get();
//如果下一条目不为null,下一条目的key为null,删除
if (k == null) {
e.value = null;
tab[i] = null;
size--;
} else {
//重新计算下一条目的hashcode,如果计算出的hashcode不等于原位置,删除该条目。从新的hashcode位置开始向后查找,查找一个null条件,存放该条目。实际此过程即为hash冲突处理的再hash过程。
int h = k.threadLocalHashCode & (len - 1);
if (h != i) {
tab[i] = null;
// Unlike Knuth 6.4 Algorithm R, we must scan until
// null because multiple entries could have been stale.
while (tab[h] != null)
h = nextIndex(h, len);
tab[h] = e;
}
}
}
return i;
}