理解ConcurrentSkipListMap 只需要理解存储方式就行了
跳表结构之下往上分层,比如需要找117,首先会判断最高层,先比较21,在比较37 ,再比较37左边的,因为左边结束了,所以只能往下走,一直找到目标为止:
寻找规则,从最高层开始,先右,再下,直到最后。
1)单个节点定义:链式。
static final class Node<K,V> { final K key; volatile Object value; volatile Node<K,V> next; /** * Creates a new regular node. */ Node(K key, Object value, Node<K,V> next) { this.key = key; this.value = value; this.next = next; }
2)单个节点,主要增加对right和down的指引
static class Index<K,V> { final Node<K,V> node; final Index<K,V> down; volatile Index<K,V> right; /** * Creates index node with given values. */ Index(Node<K,V> node, Index<K,V> down, Index<K,V> right) { this.node = node; this.down = down; this.right = right; }
3)再次包装,产生对leve的定义。
static final class HeadIndex<K,V> extends Index<K,V> { final int level; HeadIndex(Node<K,V> node, Index<K,V> down, Index<K,V> right, int level) { super(node, down, right); this.level = level; } }
如果对数据结构了解,上面headIndex 就可以构成跳表。
put的时候查找位置:
private Node<K,V> findPredecessor(Object key, Comparator<? super K> cmp) {
if (key == null)
throw new NullPointerException(); // don't postpone errors
for (;;) {//先找right
for (Index<K,V> q = head, r = q.right, d;;) {
if (r != null) {
Node<K,V> n = r.node;
K k = n.key;
if (n.value == null) {
if (!q.unlink(r))
break; // restart
r = q.right; // reread r
continue;
}
if (cpr(cmp, key, k) > 0) {
q = r;
r = r.right;
continue;
}
}
- //再找down
if ((d = q.down) == null)
return q.node;
q = d;
r = d.right;
}
}
可以看到都是先右边再下边。
不过这里的跳表有点不同,每个节点不是一个单点,而是一个链表。通过next 连接。
for (Node<K,V> b = findPredecessor(key, cmp), n = b.next;;) {
if (n != null) {
Object v; int c;
Node<K,V> f = n.next;
if (n != b.next) // inconsistent read
break;
if ((v = n.value) == null) { // n is deleted
n.helpDelete(b, f);
break;
}
if (b.value == null || v == n) // b is deleted
break;
if ((c = cpr(cmp, key, n.key)) > 0) {
b = n;
n = f;
continue;
}
if (c == 0) {
if (onlyIfAbsent || n.casValue(v, value)) {
@SuppressWarnings("unchecked") V vv = (V)v;
return vv;
}
break; // restart if lost race to replace value
}
// else c < 0; fall through
}
z = new Node<K,V>(key, value, n);
if (!b.casNext(n, z))
break; // restart if lost race to append to b
break outer;
}
}
里面还有
// find insertion points and splice in
数据的level配置,已经插入新的节点。