原文: https://javatutorial.net/java-concurrentmap-example

即使Map 由许多类实现,但其中许多不是线程安全的,或者其中一些效率不高。 这就是为什么在 Java 1.5 中引入ConcurrentMap的原因。 它是线程安全且高效的。

Java `ConcurrentMap`示例 - 图1

覆盖的默认实现:

  • count
  • replaceAll
  • forEach
  • getOrDefault
  • computerIfAbsent
  • computerIfPresent

ConcurrentMap由表示为表存储桶的节点数组组成,它们在第一次插入后初始化。

ConcurrentMapHashMap之间的效率比较

  • 如果要尽快处理数据,则必须使用所有线程,因此这意味着ConcurrentMap在这里更有效。
  • 如果只需要单线程访问,则HashMap更快。
  • 如果由HashMap实现,则添加方法的速度快 3 倍。
  • 如果由ConcurrentMap实现,则 get 方法会更快。

如果程序需要多个线程访问,则ConcurrentMap是更好的选择。 但是,如果程序仅使用 1 个线程,则HashMap将是更好的选择。

Java `ConcurrentMap`示例 - 图2

ConcurrentMap

ConcurrentMap中的方法

  1. default V compute(K key, BiFunction<? super K, ? super V, ? extends V> remappingFunction):尝试计算指定键及其当前映射值的映射。
  2. default V computeIfAbsent(K key, Function<? super K, ? extends V> mappingFunction):如果作为参数给出的键与值不相关(或为null),则尝试计算其值并输入 进入此映射,除非为null
  3. default V computeIfPresent(K key, BiFunction<? super K, ? super V, ? extends V> remappingFunction):如果指定键的值存在且非空,则尝试计算新映射,给定键及其当前映射值。
  4. default void forEach(BiConsumer<? super K, ? super V> action):对当前映射中的每个条目执行给定的操作,直到所有条目都已处理。
  5. default V getOrDefault(Object key, V defaultValue):返回指定键所映射到的值或如果映射不包含该键的映射关系,则返回defaultValue(作为第二个参数)。
  6. default V merge(K key, V value, BiFunction<? super V, ? super V, ? extends V> remappingFunction):如果键尚未与值关联或与null关联,则它将关联指定的非null值。
  7. V putIfAbsent(K key, V value):如果指定的键尚未与值关联,则将其与给定的值关联。
  8. boolean remove(Object key, Object value):仅当当前映射到给定值时,才删除键的条目。
  9. V replace(K key, V value):仅当当前映射到某个值时才替换键的条目。
  10. boolean replace(K key, V oldValue, V newValue):仅当当前映射到给定值时才替换项的条目。

有关 EnumSet 主要方法的更多信息,请随时访问原始 Oracle 文档

使用上述某些方法的示例程序

  1. import java.util.concurrent.*;
  2. class ConcurrentHashMapExample {
  3. public static void main(String[] args)
  4. {
  5. ConcurrentHashMap conCurrHashMap = new ConcurrentHashMap();
  6. conCurrHashMap.put(100, "Elephant");
  7. conCurrHashMap.put(101, "Tiger");
  8. conCurrHashMap.put(102, "Lion");
  9. conCurrHashMap.put(103, "Cow");
  10. // since 103 already exists, this won't work
  11. conCurrHashMap.putIfAbsent(103, "Goat");
  12. conCurrHashMap.remove(103, "Goat");
  13. System.out.println("After removal: " + conCurrHashMap);
  14. // since 103 was removed, this now works
  15. conCurrHashMap.putIfAbsent(103, "Leopard");
  16. System.out.println("After put: " + conCurrHashMap);
  17. // changing Goat to Cheetah
  18. conCurrHashMap.replace(103, "Leopard", "Cheetah");
  19. System.out.println("Final: " + conCurrHashMap);
  20. }
  21. }

输出

  1. After removal: {100=Elephant, 101=Tiger, 102=Lion, 103=Cow}
  2. After put: {100=Elephant, 101=Tiger, 102=Lion, 103=Cow}
  3. Final: {100=Elephant, 101=Tiger, 102=Lion, 103=Cow}