这个方法好像还挺长的,上面我们已经猜测过它的用途了,现在我们就来揭开它的庐山真面目。
首先关注一个这个方法的参数:
第一个参数就是我们的key,估摸着还是用来计算hash值找位置的;第二个就是要放的value了;第三个staleSlot呢?我们上面好像是找到了一个key为null的entry节点吧?没错,这个staleSlot就是这个节点在tab中的位置了。然后从这个staleSlot节点开始往前找,如果发现某个entry不为空,但key等于null,用slotToExpunge记录下它的位置,直到往前找到一个entry为null的节点停止。这个slotToExpunge是用来干嘛的呢?后面会提到。
我们接着看。往前找完之后,我们又从staleSlot的下一个节点开始往后找,如果发现了某个节点的键值等于我们的key。我们是不是应该用我们的value替换掉这个位置原先的值呢?好像是应该替换。但是别忘记了前面还有个key为null的entry节点呢!由于之前key为null的节点和当前节点计算出来hash值其实是一样的。这里我们将e节点的值更新为最新的value后,互换tab[i]和entry的位置。这一步的目的是什么呢?我猜大概是这样的,因为ThreadLocalMap是根据线性探测法来解决冲突的,因此可能会出现key的哈希值相同但散落位置不连续的情况。为了在一定程度上提高查找哈希值相同entry节点的效率,交换一下位置会是更好的选择。同时接下来会执行cleanSomeSlots()方法。我们上面的for循环会一直往后找,直到发现一个null节点为止。如果找到了null节点,那就说明按照线性探测法找不到这个节点了啊!那咋办呢?staleSlot节点不是空着呢么。直接塞进去不就完事了。。
最后一句又调用了cleanSomeSlots()方法。下面就轮到它了。。