Java8 ConcurrentSkipListMap与ConcurrentSkipListSet (二) 源码解析

    目录

1、compute / merge

2、higher / lower /ceiling / floor

3、first / last 

4、pollFirstEntry / pollLastEntry

5、keySet / descendingKeySet / Iter

6、tailMap / headMap / subMap /SubMap


     本篇博客继续上一篇《Java8 ConcurrentSkipListMap与ConcurrentSkipListSet (一) 源码解析》讲解ConcurrentNavigableMap相关方法的实现细节。

1、compute / merge

      compute一共有三个方法,compute、computeIfAbsent和computeIfPresent,这四个方法的实现类似,都是先找到目标key,然后用remappingFunction计算结果,方法含义跟ConcurrentHashMap中一样的,不再赘述。


public V compute(K key,
                     BiFunction<? super K, ? super V, ? extends V> remappingFunction) {
        if (key == null || remappingFunction == null)
            throw new NullPointerException();
        for (;;) {
            Node<K,V> n; Object v; V r;
            if ((n = findNode(key)) == null) { //没有找到目标节点
                if ((r = remappingFunction.apply(key, null)) == null) //计算返回null,跳出循环返回null
                    break;
                if (doPut(key, r, true) == null) //r不为null,插入新节点,doPut返回值不是null,则重新for循环,进入下面的else if分支
                    return r;
            }
            else if ((v = n.value) != null) { //找到目标节点,如果value为null,下一次循环findNode会将该节点删除
                @SuppressWarnings("unchecked") V vv = (V) v;
                if ((r = remappingFunction.apply(key, vv)) != null) { //r不为null,修改value
                    if (n.casValue(vv, r)) //cas失败,则再次for循环
                        return r;
                }
                else if (doRemove(key, vv) != null) //r为null,删除节点
                    break;
            }
        }
        return null;
    }

public V computeIfAbsent(K key,
                             Function<? super K, ? extends V> mappingFunction) {
        if (key == null || mappingFunction == null)
            throw new NullPointerException();
        V v, p, r;
        if ((v = doGet(key)) == null &&   //目标key不存在
            (r = mappingFunction.apply(key)) != null) //计算结果非空
            v = (p = doPut(key, r, true)) == null ? r : p;
        return v;
    }

  
public V computeIfPresent(K key,
                              BiFunction<? super K, ? super V, ? extends V> remappingFunction) {
        if (key == null || remappingFunction == null)
            throw new NullPointerException();
        Node<K,V> n; Object v;
        while ((n = findNode(key)) != null) { //目标key 存在且value非空
            if ((v = n.value) != null) {
                @SuppressWarnings("unchecked") V vv = (V) v;
                V r = remappingFunction.apply(key, vv);
                if (r != null) { //r不为null,修改value
                    if (n.casValue(vv, r))
                        return r;
                }
                else if (doRemove(key, vv) != null) //r为null,删除节点
                    break;
            }
        }
        return null;
    }

    
public V merge(K key, V value,
                   BiFunction<? super V, ? super V, ? extends V> remappingFunction) {
        if (key == null || value == null || remappingFunction == null)
            throw new NullPointerException();
        for (;;) {
            Node<K,V> n; Object v; V r;
            if ((n = findNode(key)) == null) { //没有匹配的key,插入新节点
                if (doPut(key, value, true) == null)
                    return value;
            }
            else if ((v = n.value) != null) { //找到目标key
                @SuppressWarnings("unchecked") V vv = (V) v;
                if ((r = remappingFunction.apply(vv, value)) != null) { //r不为null,修改value
                    if (n.casValue(vv, r)) 
                        return r;
                }
                else if (doRemove(key, vv) != null) //r为null,删除节点
                    return null;
            }
        }
    }

2、higher / lower /ceiling / floor

    这四个,每个都有两个方法,如ceilingKey和ceilingEntry,前者返回Key,后者返回一个Map.Entry键值对,总共8个方法;其中higher和lower相对,lower表示获取小于key的最大节点,higher表示获取大于key的最小节点;ceiling 与 floor相对,floor表示获取小于或者等于key的最大节点,ceiling 表示获取大于或者等于key的最小节点,其实现如下:

public Map.Entry<K,V> lowerEntry(K key) {
        //找到小于key的最大节点
        return getNear(key, LT);
    }

public K lowerKey(K key) {
        Node<K,V> n = findNear(key, LT, comparator);
        return (n == null) ? null : n.key;
    }

public Map.Entry<K,V> higherEntry(K key) {
       //找到大于key的最小节点
        return getNear(key, GT);
    }

    
public K higherKey(K key) {
        Node<K,V> n = findNear(key, GT, comparator);
        return (n == null) ? null : n.key;
    }

public Map.Entry<K,V> floorEntry(K key) {
        //找到小于或者等于key的最大节点
        return getNear(key, LT|EQ);
    }

public K floorKey(K key) {
        Node<K,V> n = findNear(key, LT|EQ, comparator);
        return (n == null) ? null : n.key;
    }

   
public Map.Entry<K,V> ceilingEntry(K key) {
         //找到大于或者等于key的最小节点
        return getNear(key, GT|EQ);
    }

    
public K ceilingKey(K key) {
        Node<K,V> n = findNear(key, GT|EQ, comparator);
        return (n == null) ? null : n.key;
    }

//rel是一个常量
final Node<K,V> findNear(K key, int rel, Comparator<? super K> cmp) {
        if (key == null)
            throw new NullPointerException();
        for (;;) {
            //找到最底层中接近key且小于key的节点b,然后往后遍历
            for (Node<K,V> b = findPredecessor(key, cmp), n = b.next;;) {
                Object v;
                if (n == null) //遍历万彩城
                    return ((rel & LT) ==
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值