2 * Licensed to the Apache Software Foundation (ASF) under one
3 * or more contributor license agreements. See the NOTICE file
4 * distributed with this work for additional information
5 * regarding copyright ownership. The ASF licenses this file
6 * to you under the Apache License, Version 2.0 (the
7 * "License"); you may not use this file except in compliance
8 * with the License. You may obtain a copy of the License at
10 * http://www.apache.org/licenses/LICENSE-2.0
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
19 package org
.apache
.hadoop
.hbase
.util
;
21 import java
.io
.IOException
;
22 import java
.util
.concurrent
.ConcurrentMap
;
23 import java
.util
.function
.Supplier
;
25 import org
.apache
.yetus
.audience
.InterfaceAudience
;
28 * Utility methods for dealing with Collections, including treating null collections as empty.
30 @InterfaceAudience.Private
31 public class ConcurrentMapUtils
{
34 * In HBASE-16648 we found that ConcurrentHashMap.get is much faster than computeIfAbsent if the
35 * value already exists. Notice that the implementation does not guarantee that the supplier will
36 * only be executed once.
38 public static <K
, V
> V
computeIfAbsent(ConcurrentMap
<K
, V
> map
, K key
, Supplier
<V
> supplier
) {
39 return computeIfAbsent(map
, key
, supplier
, () -> {
44 * A supplier that throws IOException when get.
47 public interface IOExceptionSupplier
<V
> {
48 V
get() throws IOException
;
52 * In HBASE-16648 we found that ConcurrentHashMap.get is much faster than computeIfAbsent if the
53 * value already exists. So here we copy the implementation of
54 * {@link ConcurrentMap#computeIfAbsent(Object, java.util.function.Function)}. It uses get and
55 * putIfAbsent to implement computeIfAbsent. And notice that the implementation does not guarantee
56 * that the supplier will only be executed once.
58 public static <K
, V
> V
computeIfAbsentEx(ConcurrentMap
<K
, V
> map
, K key
,
59 IOExceptionSupplier
<V
> supplier
) throws IOException
{
61 return ((v
= map
.get(key
)) == null && (newValue
= supplier
.get()) != null
62 && (v
= map
.putIfAbsent(key
, newValue
)) == null) ? newValue
: v
;
65 public static <K
, V
> V
computeIfAbsent(ConcurrentMap
<K
, V
> map
, K key
, Supplier
<V
> supplier
,
66 Runnable actionIfAbsent
) {
71 V newValue
= supplier
.get();
72 v
= map
.putIfAbsent(key
, newValue
);