Java ConcurrentMap示例

时间:2020-02-23 14:37:06  来源:igfitidea点击:

尽管Map由许多类实现,但其中许多类不是线程安全的,或者其中一些类的效率不高。这就是为什么在Java1.5中引入了ConcurrentMap。它是线程安全和高效的。

覆盖的默认实现:

  • compute
  • replaceAll
  • forEach
  • getOrDefault
  • computerIfAbsent
  • computerIfPresent

ConcurrentMap由一个节点数组组成,这些节点用表bucket表示,它们在第一次插入之后被初始化。

ConcurrentMap与HashMap的效率比较

如果想要尽可能快地对数据进行操作,那么必须使用所有线程,这意味着ConcurrentMap在这里更有效。

如果只需要一个线程访问,HashMap会更快。

如果使用HashMap实现add方法,则速度将提高3倍。

如果用ConcurrentMap实现get方法会更快。

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

并发图

ConcurrentMap中的方法

默认V计算(K键,双函数<?超级K?超级V?extends V>remappingFunction):尝试计算指定键及其当前映射值的映射。

默认V computeIfAbsent(K键,函数<?超级K?extends V>mappingFunction):如果作为参数给定的键与值(或者null)不关联,则尝试计算其值并将其输入此映射,除非为null。

默认V computeIfPresent(K键,BiFunction<?超级K?超级V?extends V>remappingFunction):如果指定键的值存在且非空,则尝试计算给定键及其当前映射值的新映射。

默认void forEach(BiConsumer<?超级K?super V>action):对当前映射中的每个条目执行给定的操作,但所有条目都已处理。

default V getOrDefault(Object key,V defaultValue):返回指定键映射到的值;如果映射不包含该键的映射,则返回defaultValue(作为第二个参数给定)。

默认V merge(K键,V值,BiFunction<?超级V?超级V?extends V>remappingFunction):如果键尚未与值关联或者与null关联,则它将其与指定的非null值关联。

V putIfAbsent(K key,V value):如果指定的键尚未与值关联,请将其与给定值关联。

boolean remove(Object key,Object value):仅当当前映射到给定值时,才删除键的条目。

V replace(K key,V value):仅当当前映射到某个值时才替换键的条目。

boolean replace(K key,V oldValue,V newValue):仅当当前映射到给定值时才替换键的条目。

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

使用上述方法的示例程序

import java.util.concurrent.*; 
class ConcurrentHashMapExample { 
  public static void main(String[] args) 
  { 
      ConcurrentHashMap conCurrHashMap = new ConcurrentHashMap(); 
      conCurrHashMap.put(100, "Elephant"); 
      conCurrHashMap.put(101, "Tiger"); 
      conCurrHashMap.put(102, "Lion"); 
      conCurrHashMap.put(103, "Cow"); 

      //since 103 already exists, this won't work
      conCurrHashMap.putIfAbsent(103, "Goat"); 

      conCurrHashMap.remove(103, "Goat"); 
      System.out.println("After removal: " + conCurrHashMap);

      //since 103 was removed, this now works
      conCurrHashMap.putIfAbsent(103, "Leopard"); 
      System.out.println("After put: " + conCurrHashMap);

      //changing Goat to Cheetah
      conCurrHashMap.replace(103, "Leopard", "Cheetah"); 
      System.out.println("Final: " + conCurrHashMap); 
  } 
}

输出

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