查看原文
其他

JDK1.8 ConcurrentHashMap的size

2017-11-02 白玉 IT哈哈

旧版本方法,和推荐的mappingCount返回的值基本无区别 


   public int size() {
        long n = sumCount();
        return ((n < 0L) ? 0 :
                (n > (long)Integer.MAX_VALUE) ? Integer.MAX_VALUE :
                (int)n);
    }


这个方法是从JDK1.2版本开始就有的方法了。而ConcurrentHashMap在JDK1.8版本中还提供了另外一种方法可以获取大小,这个方法就是mappingCount。


public long mappingCount() {
        long n = sumCount();
        return (n < 0L) ? 0L : n; // ignore transient negative values
}


根据mappingCount()方法头上的注释,我们可以得到如下的信息:

1、这个应该用来代替size()方法被使用。这是因为ConcurrentHashMap可能比包含更多的映射结果,即超过int类型的最大值。

2、这个方法返回值是一个估计值,由于存在并发的插入和删除,因此返回值可能与实际值会有出入。

虽然注释这么才说使用mappingCount来代替size()方法,但是我们比较两个方法的源码你会发现这两个方法的源码基本一致。

在size()方法和mappingCount方法中都出现了sumCount()方法,因此,我们也顺便看一下。

在size()方法和mappingCount方法中都出现了sumCount()方法,因此,我们也顺便看一下。


    // Table of counter cells. When non-null, size is a power of 2
    private transient volatile CounterCell[] counterCells;
    //ConcurrentHashMap中元素个数,基于CAS无锁更新,但返回的不一定是当前Map的真实元素个数。
    private transient volatile long baseCount;

/**
     * A padded cell for distributing counts.  Adapted from LongAdder
     * and Striped64.  See their internal docs for explanation.
     */
    @sun.misc.Contended static final class CounterCell {
        volatile long value;
        CounterCell(long x) { value = x; }
    }

    final long sumCount() {
        CounterCell[] as = counterCells; CounterCell a;
        long sum = baseCount;
        if (as != null) {
            for (int i = 0; i < as.length; ++i) {
                if ((a = as[i]) != null)
                    sum += a.value;
            }
        }
        return sum;
    }


您可能也对以下帖子感兴趣

文章有问题?点此查看未经处理的缓存