java中的ConcurrentMap接口
ConcurrentMap 是一个接口,它是Java集合框架的成员,在JDK 1.5中引入,表示一个能够处理并发访问的地图,而不影响地图中条目的一致性。ConcurrentMap接口存在于 java.util.concurrent 包中。除了从SuperInterface即java.util.Map继承的方法外,它还提供了一些额外的方法。它继承了嵌套接口Map.Entry<K, V>
。
HashMap的操作是不同步的,而Hashtable提供了同步性。尽管Hashtable是一个线程安全的,但它的效率并不高。为了解决这个问题,Java集合框架在Java 1.5中引入了 ConcurrentMap
ConcurrentMap的层次结构
声明 。
public interface ConcurrentMap<K,V> extends Map<K,V>
这里, K 是key Object的类型, V 是value Object的类型。
- 它扩展了Java中的Map接口。
- ConcurrentNavigableMap<K,V>是子接口。
- ConcurrentMap由ConcurrentHashMap、 ConcurrentSkipListMap 类实现。
- ConcurrentMap被称为同步Map。
实现的类
由于它属于 java.util.concurrent 包,所以我们必须用以下方式导入
import java.util.concurrent.ConcurrentMap
or
import java.util.concurrent.*
ConcurrentMap有两个实现类,即 ConcurrentSkipListMap 和 ConcurrentHashMap。 ConcurrentSkipListMap是ConcurrentNavigableMap接口的一个可扩展的实现,它扩展了ConcurrentMap接口。ConcurrentSkipListMap中的键是按自然顺序排序的,或者在构造对象时使用比较器。ConcurrentSkipListMap的插入、删除和搜索操作的预期时间成本为 log(n) 。它是一个线程安全的类,因此,所有的基本操作都可以并发地完成。
语法
// ConcurrentMap implementation by ConcurrentHashMap
CocurrentMap<K, V> numbers = new ConcurrentHashMap<K, V>();
// ConcurrentMap implementation by ConcurrentSkipListMap
ConcurrentMap< ? , ? > objectName = new ConcurrentSkipListMap< ? , ? >();
例如:
// Java Program to illustrate methods
// of ConcurrentMap interface
import java.util.concurrent.*;
class ConcurrentMapDemo {
public static void main(String[] args)
{
// Since ConcurrentMap is an interface,
// we create instance using ConcurrentHashMap
ConcurrentMap<Integer, String> m = new ConcurrentHashMap<Integer, String>();
m.put(100, "Geeks");
m.put(101, "For");
m.put(102, "Geeks");
// Here we cant add Hello because 101 key
// is already present
m.putIfAbsent(101, "Hello");
// We can remove entry because 101 key
// is associated with For value
m.remove(101, "For");
// Now we can add Hello
m.putIfAbsent(101, "Hello");
// We can replace Hello with For
m.replace(101, "Hello", "For");
System.out.println("Map contents : " + m);
}
}
输出
Map contents : {100=Geeks, 101=For, 102=Geeks}
基本方法
1.添加元素
ConcurrentSkipListMap的put()方法是Java中的一个内置函数,它将指定的值与该地图中的指定键联系起来。如果该地图以前包含了该键的映射,那么旧的值将被替换。
// Java Program to demonstrate adding
// elements
import java.util.concurrent.*;
class AddingElementsExample {
public static void main(String[] args)
{
// Instantiate an object
// Since ConcurrentMap
// is an interface so We use
// ConcurrentSkipListMap
ConcurrentMap<Integer, Integer> mpp = new ConcurrentSkipListMap<Integer, Integer>();
// Adding elements to this map
// using put() method
for (int i = 1; i <= 5; i++)
mpp.put(i, i);
// Print map to the console
System.out.println("After put(): " + mpp);
}
}
输出
After put(): {1=1, 2=2, 3=3, 4=4, 5=5}
2.移除元素
ConcurrentSkipListMap的remove()方法是Java中的一个内置函数,可以从该地图中移除指定键的映射。如果没有该特定键的映射,该方法返回null。执行该方法后,地图的大小会减少。
// Java Program to demonstrate removing
// elements
import java.util.concurrent.*;
class RemovingElementsExample {
public static void main(String[] args)
{
// Instantiate an object
// Since ConcurrentMap
// is an interface so We use
// ConcurrentSkipListMap
ConcurrentMap<Integer, Integer> mpp = new ConcurrentSkipListMap<Integer, Integer>();
// Adding elements to this map
// using put method
for (int i = 1; i <= 5; i++)
mpp.put(i, i);
// remove() mapping associated
// with key 1
mpp.remove(1);
System.out.println("After remove(): " + mpp);
}
}
输出
After remove(): {2=2, 3=3, 4=4, 5=5}
3.访问元素
我们可以使用get()方法访问ConcurrentSkipListMap的元素,下面给出了这个例子。
// Java Program to demonstrate accessing
// elements
import java.util.concurrent.*;
class AccessingElementsExample {
public static void main(String[] args)
{
// Instantiate an object
// Since ConcurrentMap
// is an interface so We use
// ConcurrentSkipListMap
ConcurrentMap<Integer, String> chm = new ConcurrentSkipListMap<Integer, String>();
// insert mappings using put method
chm.put(100, "Geeks");
chm.put(101, "for");
chm.put(102, "Geeks");
chm.put(103, "Contribute");
// Displaying the HashMap
System.out.println("The Mappings are: ");
System.out.println(chm);
// Display the value of 100
System.out.println("The Value associated to "
+ "100 is : " + chm.get(100));
// Getting the value of 103
System.out.println("The Value associated to "
+ "103 is : " + chm.get(103));
}
}
输出
The Mappings are:
{100=Geeks, 101=for, 102=Geeks, 103=Contribute}
The Value associated to 100 is : Geeks
The Value associated to 103 is : Contribute
4.遍历
我们可以使用Iterator接口来遍历集合框架的任何结构。由于迭代器只处理一种类型的数据,我们使用Entry< ?, ? >来将两种不同的类型解析成一种兼容的格式。然后使用next()方法,我们打印ConcurrentSkipListMap的元素。
import java.util.concurrent.*;
import java.util.*;
public class TraversingExample {
public static void main(String[] args)
{
// Instantiate an object
// Since ConcurrentMap
// is an interface so We use
// ConcurrentSkipListMap
ConcurrentMap<Integer, String> chmap = new ConcurrentSkipListMap<Integer, String>();
// Add elements using put()
chmap.put(8, "Third");
chmap.put(6, "Second");
chmap.put(3, "First");
chmap.put(11, "Fourth");
// Create an Iterator over the
// ConcurrentSkipListMap
Iterator<ConcurrentSkipListMap
.Entry<Integer, String> > itr
= chmap.entrySet().iterator();
// The hasNext() method is used to check if there is
// a next element The next() method is used to
// retrieve the next element
while (itr.hasNext()) {
ConcurrentSkipListMap
.Entry<Integer, String> entry
= itr.next();
System.out.println("Key = " + entry.getKey()
+ ", Value = "
+ entry.getValue());
}
}
}
输出
Key = 3, Value = First
Key = 6, Value = Second
Key = 8, Value = Third
Key = 11, Value = Fourth
ConcurrentMap的方法
- K – 地图中键的类型。
- V – 在地图中映射的值的类型。
方法 | 描述 |
---|---|
compute(K key, BiFunction<? super K,? super V,? extends V> remappingFunction) | 试图为指定的键和其当前映射的值计算一个映射(如果没有当前映射,则为空)。 |
computeIfAbsent(K key, Function<? super K,? extends V> mappingFunction) | 如果指定的键还没有与一个值相关联(或者被映射为空),则尝试使用给定的映射函数计算其值,并将其输入此映射,除非为空。 |
computeIfPresent(K key, BiFunction<? super K,? super V,? extends V> remappingFunction) | 如果指定的键的值是存在的,并且不是空的,则尝试给定键和其当前的映射值来计算一个新的映射。 |
forEach(BiConsumer<? super K,? super V> action) | 对这个地图中的每个条目执行给定的动作,直到所有条目都被处理完,或者该动作抛出一个异常。 |
getOrDefault(Object key, V defaultValue) | 返回指定的键被映射到的值,如果这个地图不包含键的映射,则返回defaultValue。 |
merge(K key, V value, BiFunction<? super V,? super V,? extends V> remappingFunction) | 如果指定的键还没有与一个值关联,或者与空值关联,那么就把它与给定的非空值关联起来。 |
putIfAbsent(K key, V value) | 如果指定的键还没有与一个值相关联,则将其与给定的值相关联。 |
remove(Object key, Object value) | 仅当当前映射到给定的值时,删除键的条目。 |
replace(K key, V value) | 只在当前映射到某个值的情况下替换键的条目。 |
replace(K key, V oldValue, V newValue) | 仅当当前映射到一个给定的值时,替换键的条目。 |
replaceAll(BiFunction<? super K,? super V,? extends V> function) | 用对该条目调用给定函数的结果替换每个条目的值,直到所有条目都被处理完或该函数抛出一个异常。 |
从java.util.Map接口继承的方法
方法 | 描述 |
---|---|
清除() | 移除该地图中的所有映射(可选操作)。 |
containsKey(Object key) | 如果这个地图包含指定键的映射,返回true。 |
containsValue(Object value) | 如果这个地图将一个或多个键映射到指定的值,则返回true。 |
entry(K k, V v) | 返回一个包含给定键和值的不可变的Map.Entry。 |
entrySet() | 返回该地图中包含的映射的Set视图。 |
equals(Object o) | 将指定的对象与该地图进行平等比较。 |
get(Object key) | 返回指定的键被映射到的值,如果此地图不包含键的映射,则返回空值。 |
hashCode() | 返回该地图的哈希代码值。 |
isEmpty() | 如果这个地图不包含键值映射,则返回true。 |
keySet() | 返回该地图中包含的键的Set视图。 |
of() | 返回一个包含零映射的不可变的地图。 |
of(K k1, V v1) | 返回一个包含单一映射的不可变的地图。 |
of(K k1, V v1, K k2, V v2) | 返回一个包含两个映射的不可变的地图。 |
of(K k1, V v1, K k2, V v2, K k3, V v3) | 返回一个包含三个映射的不可变的映射。 |
of(K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4) | 返回一个包含四个映射的不可变的映射。 |
of(K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4, K k5, V v5) | 返回一个包含五个映射的不可变的地图。 |
of(K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4, K k5, V v5, K k6, V v6) | 返回一个包含六个映射的不可变的地图。 |
of(K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4, K k5, V v5, K k6, V v6, K k7, V v7) | 返回一个包含七个映射的不可变的地图。 |
of(K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4, K k5, V v5, K k6, V v6, K k7, V v7, K k8, V v8) | 返回一个包含八个映射的不可变的地图。 |
of(K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4, K k5, V v5, K k6, V v6, K k7, V v7, K k8, V v8, K k9, V v9) | 返回一个包含九个映射的不可变的地图。 |
of(K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4, K k5, V v5, K k6, V v6, K k7, V v7, K k8, V v8, K k9, V v9, K k10, V v10) | 返回一个包含十个映射的不可变的地图。 |
ofEntries(Map.Entry<? extends K,? extends V>… entries) | 返回一个包含从给定条目中提取的键和值的不可变的地图。 |
put(K key, V value) | 将指定的值与该地图中的指定键关联起来(可选操作)。 |
putAll(Map<? extends K,? extends V> m) | 将指定地图中的所有映射复制到此地图中(可选操作)。 |
remove(Object key) | 从这个地图中删除键的映射,如果它存在的话(可选操作)。 |
size() | 返回这个地图中的键值映射的数量。 |
values() | 返回该地图中包含的值的集合视图。 |
参考资料: https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/util/concurrent/ConcurrentMap.html