ThinkChat2.0新版上线,更智能更精彩,支持会话、画图、阅读、搜索等,送10W Token,即刻开启你的AI之旅 广告
![](https://cdn.zimug.com/wx-zimug.png) 在之前的文章中已经为大家介绍了java并发编程的工具:BlockingQueue接口、ArrayBlockingQueue、DelayQueue、LinkedBlockingQueue、PriorityBlockingQueue、SynchronousQueue、BlockingDeque接口,本文为系列文章第八篇。 由于Java程序员常用的HashMap的操作方法不是同步的,所以在多线程环境下会导致存取操作数据不一致的问题,Map接口的另一个实现类Hashtable 虽然是线程安全的,但是在多线程下执行效率很低。为了解决这个问题,在java 1.5版本中引入了线程安全的集合类**ConcurrentMap**。 ![](http://cdn.zimug.com/0f3be0dc1ea362de1e8be9091877cb0e) `java.util.concurrent.ConcurrentMap`接口是Java集合类框架提供的线程安全的map,这意味着多线程同时访问它,不会影响map中每一条数据的一致性。ConcurrentMap接口有两个实现类ConcurrentHashMap和ConcurrentSkipListMap,经常被使用的是ConcurrentHashMap,我们来重点关注它。 ## 1.创建ConcurrentHashMap对象 通过下面的代码创建ConcurrentHashMap ~~~ // 创建容量为8,负载系数为0.6的ConcurrentHashMap ConcurrentHashMap<Key, Value> numbers = new ConcurrentHashMap<>(8, 0.6f); ~~~ 使用上面的代码,我们创建一个叫做numbers的ConcurrentHashMap对象。 * Key - 用于关联Map中每个元素的唯一标识 * Value - Map中每个元素,可以通过key值获取value 需要我们特别注意的是`new ConcurrentHashMap<>(8, 0.6)`. * **capacity容量** - 第一个参数表示这个map的容量是8,也就是说这个对象可以存储8个键值对. * **loadFactor负载因子** - 这个map对象的负载因子是 0.6. 这意味着,每当我们的哈希表被填满60%的时候,条目就会被移动到一个新的哈希表,其容量大小是原来哈希表的两倍。 **默认容量与负载因子** 我们还可以通过下面的代码初始化一个ConcurrentHashMap对象,默认情况下capacity=16,loadFactor=0.75 ~~~ ConcurrentHashMap<Key, Value> numbers1 = new ConcurrentHashMap<>(); ~~~ ## 2.ConcurrentHashMap常用方法 ### 2.1. 向ConcurrentHashMap插入元素 * `put(K,V)` - 向map中插入key/value 键值对数据 * `putAll(map)` - 把另一个map中的所有entries插入到当前的map中 * `putIfAbsent(K,V)` - 向map中插入key/value 键值对数据,如果该键值对的key在map不存在则插入数据,否则不做操作。 ~~~ import java.util.concurrent.ConcurrentHashMap; class Main { public static void main(String[] args) { // 创建ConcurrentHashMap 用于保存偶数 ConcurrentHashMap<String, Integer> evenNumbers = new ConcurrentHashMap<>(); // 使用put()方法插入数据 evenNumbers.put("Two", 2); evenNumbers.put("Four", 4); // 使用putIfAbsent()插入数据 evenNumbers.putIfAbsent("Six", 6); System.out.println("偶数集合ConcurrentHashMap: " + evenNumbers); //创建ConcurrentHashMap用于保存整数 ConcurrentHashMap<String, Integer> numbers = new ConcurrentHashMap<>(); numbers.put("One", 1); // 使用putAll()插入数据 numbers.putAll(evenNumbers); System.out.println("整数集合ConcurrentHashMap: " + numbers); } } ~~~ **输出结果:** ~~~ 偶数集合ConcurrentHashMap: {Six=6, Four=4, Two=2} 整数集合ConcurrentHashMap: {Six=6, One=1, Four=-4, Two=2} ~~~ ### 2.2.批量获取ConcurrentHashMap 元素 * `entrySet()`- 获取 map中key/value 键值对集合 * `keySet()`- 获取map中所有的key的集合 * `values()`- 获取map中所有的value的集合 ~~~ import java.util.concurrent.ConcurrentHashMap; class Main { public static void main(String[] args) { ConcurrentHashMap<String, Integer> numbers = new ConcurrentHashMap<>(); numbers.put("One", 1); numbers.put("Two", 2); numbers.put("Three", 3); System.out.println("ConcurrentHashMap: " + numbers); // 获取 map中key/value 键值对集合 System.out.println("Key/Value mappings: " + numbers.entrySet()); // 获取map中所有的key的集合 System.out.println("Keys: " + numbers.keySet()); // 获取map中所有的value的集合 System.out.println("Values: " + numbers.values()); } } ~~~ **输出结果** ~~~ ConcurrentHashMap: {One=1, Two=2, Three=3} Key/Value mappings: [One=1, Two=2, Three=3] Keys: [One, Two, Three] Values: [1, 2, 3] ~~~ ### 2.3. 获取指定Key元素的value值 * `get()` - 获取指定key元素的value值,如果key不存在返回null * `getOrDefault()` - 获取指定key元素的value值,如果key不存在返回一个指定的默认值 ~~~ import java.util.concurrent.ConcurrentHashMap; class Main { public static void main(String[] args) { ConcurrentHashMap<String, Integer> numbers = new ConcurrentHashMap<>(); numbers.put("One", 1); numbers.put("Two", 2); numbers.put("Three", 3); System.out.println("ConcurrentHashMap: " + numbers); // 获取指定key元素的value值,如果key不存在返回null int value1 = numbers.get("Three"); System.out.println("Using get(): " + value1); // 获取指定key元素的value值,如果key不存在返回一个指定的默认值 int value2 = numbers.getOrDefault("Five", 5); System.out.println("Using getOrDefault(): " + value2); } } ~~~ **输出结果** ~~~ ConcurrentHashMap: {One=1, Two=2, Three=3} Using get(): 3 Using getOrDefault(): 5 ~~~ ### 2.4.移除ConcurrentHashMap中的元素 * `remove(key)` - 根据指定的key删除map中的元素,并将该元素返回 * `remove(key, value)` - 只有当map中存在指定的键映射到指定的值时,才会从map中删除条目,并返回一个布尔值。返回true表示删除成功,否则表示map中没有这个键值对。 ~~~ import java.util.concurrent.ConcurrentHashMap; class Main { public static void main(String[] args) { ConcurrentHashMap<String, Integer> numbers = new ConcurrentHashMap<>(); numbers.put("One", 1); numbers.put("Two", 2); numbers.put("Three", 3); System.out.println("ConcurrentHashMap: " + numbers); // 根据指定的key删除map中的元素,并将该元素返回 int value = numbers.remove("Two"); System.out.println("Removed value: " + value); // 只有当map中存在指定的键映射到指定的值时,才会从map中删除条目,并返回一个布尔值。 boolean result = numbers.remove("Three", 3); System.out.println("Is the entry {Three=3} removed? " + result); System.out.println("Updated ConcurrentHashMap: " + numbers); } } ~~~ **输出结果** ~~~ ConcurrentHashMap: {One=1, Two=2, Three=3} Removed value: 2 Is the entry {Three=3} removed? True Updated ConcurrentHashMap: {One=1} ~~~