java中的ConcurrentMap接口

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的层次结构

java中的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有两个实现类,即 ConcurrentSkipListMapConcurrentHashMap。 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

Python教程

Java教程

Web教程

数据库教程

图形图像教程

大数据教程

开发工具教程

计算机教程