JDK1.8 ConcurrentHashMap的size
旧版本方法,和推荐的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;
}