HBASE-24163 MOB compactor implementations should use format specifiers when calling...
[hbase.git] / hbase-common / src / main / java / org / apache / hadoop / hbase / util / ConcurrentMapUtils.java
blobeae599b0bdcdc4b4d72430271f30c7c19c89c1a3
1 /*
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;
27 /**
28 * Utility methods for dealing with Collections, including treating null collections as empty.
30 @InterfaceAudience.Private
31 public class ConcurrentMapUtils {
33 /**
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, () -> {
40 });
43 /**
44 * A supplier that throws IOException when get.
46 @FunctionalInterface
47 public interface IOExceptionSupplier<V> {
48 V get() throws IOException;
51 /**
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 {
60 V v, newValue;
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) {
67 V v = map.get(key);
68 if (v != null) {
69 return v;
71 V newValue = supplier.get();
72 v = map.putIfAbsent(key, newValue);
73 if (v != null) {
74 return v;
76 actionIfAbsent.run();
77 return newValue;