Java ConcurrentMap示例
尽管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}