public RAMQueueEntry get(BlockCacheKey key) {
      return delegate.computeIfPresent(key, (k, re) -> {
        // It'll be referenced by RPC, so retain atomically here. if the get and retain is not
        // atomic, another thread may remove and release the block, when retaining in this thread we
        // may retain a block with refCnt=0 which is disallowed. (see HBASE-22422)
        re.getData().retain();
        return re;
      });
    }
Defined the map as {@link ConcurrentHashMap} explicitly here, because in
{@link RAMCache#get(BlockCacheKey)} and
{@link RAMCache#putIfAbsent(BlockCacheKey, BucketCache.RAMQueueEntry)} , we need to guarantee
the atomicity of map#computeIfPresent(key, func) and map#putIfAbsent(key, func). Besides, the
func method can execute exactly once only when the key is present(or absent) and under the
lock context. Otherwise, the reference count of block will be messed up. Notice that the
{@link java.util.concurrent.ConcurrentSkipListMap} can not guarantee that.
hbase-server/src/main/java/org/apache/hadoop/hbase/io/hfile/bucket/BucketCache.java