Java 中的 ConcurrentMap 接口

Java 中的 ConcurrentMap 接口

ConcurrentMapJava Collections Framework 的成员之一,它被引入 JDK 1.5 中,表示一种 Map,它能够处理并发访问,而不会影响 map 条目的一致性。ConcurrentMap 接口位于 java.util.concurrent 包中,除了从超级接口 java.util.Map 继承的方法外,还提供了一些额外的方法。它继承了嵌套接口 Map.Entry<K, V>。

HashMap 操作不是同步的,而 Hashtable 提供了同步。虽然 Hashtable 是线程安全的,但它不太高效。为了解决这个问题,Java Collections Framework 在 Java 1.5中引入了 ConcurrentMap

ConcurrentMap 的层次结构

Java 中的 ConcurrentMap 接口

声明:

public interface ConcurrentMap<K,V> extends Map<K,V>

这里, K 是键 Object 的类型,而 V 是值 Object 的类型。

  • 它继承 java.util.Map 接口。
  • ConcurrentNavigableMap<K,V> 是子接口。
  • ConcurrentMap 由 ConcurrentHashMap、 ConcurrentHashMapSkipListMap 类实现。
  • ConcurrentMap 被称为同步 Map。

实现类

由于它属于 java.util.concurrent 包,我们必须使用以下导入语句导入它

import java.util.concurrent.ConcurrentMap
                or
import java.util.concurrent.*

ConcurrentMap 有两个实现类, ConcurrentSkipListMapConcurrentHashMap 。ConcurrentSkipListMap 是 ConcurrentNavigableMap 接口的可扩展实现,该接口扩展了 ConcurrentMap 接口。ConcurrentSkipListMap 中的键通过自然顺序或在对象构造时使用比较器进行排序。ConcurrentSkipListMap 在插入、删除和搜索操作的时间成本期望为 log(n) ,它是一个线程安全的类,因此,所有基本操作均可以并发完成。

语法:

// ConcurrentHashMap 实现的 ConcurrentMap
CocurrentMap<K, V> numbers = new ConcurrentHashMap<K, V>();

// ConcurrentSkipListMap 实现的 ConcurrentMap
ConcurrentMap< ? , ? > objectName = new ConcurrentSkipListMap< ? , ? >();

例子:

// 演示 ConcurrentMap 接口的方法的 Java 程序
import java.util.concurrent.*;

class ConcurrentMapDemo {
    public static void main(String[] args) {
        // 由于 ConcurrentMap 是一个接口,所以我们使用 ConcurrentHashMap 创建实例
        ConcurrentMap<Integer, String> m = new ConcurrentHashMap<Integer, String>();
        m.put(100, "Geeks");
        m.put(101, "For");
        m.put(102, "Geeks");

        // 因为 101 键已经存在,所以我们不能添加 Hello
        m.putIfAbsent(101, "Hello");

        // 我们可以删除条目,因为 101 键关联 For 值
        m.remove(101, "For");

        // 现在我们可以添加 Hello
        m.putIfAbsent(101, "Hello");

        // 我们可以用 For 替换 Hello
        m.replace(101, "Hello", "For");
        System.out.println("Map contents : " + m);
    }
}

输出

映射内容:{100=Geeks,101=For,102=Geeks} 

基本方法

1. 添加元素

ConcurrentSkipListMap的put()方法是Java中的内置函数,它将指定的值与此映射中的指定键相关联。如果地图先前包含键的映射,则替换旧值。

// Java程序示例添加
// elements
  
import java.util.concurrent.*;
  
class AddingElementsExample {
    public static void main(String[] args)
    {
        //实例化对象
        //因为ConcurrentMap
        //是一个接口,所以我们使用
        //ConcurrentSkipListMap
        ConcurrentMap<Integer,Integer> mpp = new ConcurrentSkipListMap<Integer,Integer>();
  
        //使用put()方法将元素添加到此映射中
          为(int i =1; i <= 5; i ++)
            mpp.put(i,i);
  
        //将映射打印到控制台
        System.out.println(“ put()后:“+ mpp);
    }
} ```  

输出

put()后:{1 = 1,2 = 2,3 = 3,4 = 4,5 = 5} 

2. 删除元素

ConcurrentSkipListMap的remove()方法是Java中的内置函数,它从此地图中删除指定键的映射。如果该特定键的映射不存在,则该方法返回null。执行此方法后,地图的大小会减小。

// Java程序示例删除
// elements
  
import java.util.concurrent.*;
  
class RemovingElementsExample {
    public static void main(String[] args)
    {
        //实例化对象
        //因为ConcurrentMap
        //是一个接口,所以我们使用
        //ConcurrentSkipListMap
        ConcurrentMap<Integer,Integer> mpp = new ConcurrentSkipListMap<Integer,Integer>();
  
        //使用put方法将元素添加到该映射中
        为(int i =1; i <= 5; i ++)
            mpp.put(i,i);
  
        //删除与key 1关联的打印映射
        mpp.remove(1);
  
        System.out.println(“ remove()后:“+ mpp);
    }
} ```  

输出

remove()后:{2 = 2,3 = 3,4 = 4,5 = 5} 

3. 访问元素

我们可以使用get()方法访问ConcurrentSkipListMap的元素,下面给出示例。

// Java程序演示访问
// elements
  
import java.util.concurrent.*;
  
class AccessingElementsExample {
  
    public static void main(String[] args)
    {
  
        //实例化对象
        //因为ConcurrentMap
        //是一个接口,所以我们使用
        //ConcurrentSkipListMap
        ConcurrentMap<Integer,String> chm = new ConcurrentSkipListMap<Integer,String>();
  
        //使用put方法插入映射
        chm.put(100,“Geeks”);
        chm.put(101,“for”);
        chm.put(102,“Geeks”);
        chm.put(103,“Contribute”);
  
        //显示HashMap
        System.out.println(“ Mappings are:“);
        System.out.println(chm);
  
        //显示100的值
        System.out.println(“与
                           +“ 100相关的值为:“+ chm.get(100));
  
        //获取103的值
        System.out.println(“与
                           +“ 103相关的值为:“+ chm.get(103));
    }
} ```  

输出

映射为:
{100 = Geeks,101 = for,102 = Geeks,103 = Contribute}
与100相关联的值是:Geeks
与103相关的值为:Contribute 

4. 遍历

我们可以使用Iterator接口来遍历Collection Framework的任何结构。由于Iterator使用一种数据类型,我们要使用Entry< ? , ? >将两个不同的类型解析为兼容的格式。然后,使用next()方法输出ConcurrentSkipListMap的元素。

import java.util.concurrent.*;
import java.util.*;
  
public class TraversingExample {
    public static void main(String[] args)
    {
        // 实例化对象
        // 由于ConcurrentMap是一个接口,因此我们使用ConcurrentSkipListMap
        ConcurrentMap<Integer, String> chmap = new ConcurrentSkipListMap<Integer, String>();
  
        // 使用put()添加元素
        chmap.put(8, "Third");
        chmap.put(6, "Second");
        chmap.put(3, "First");
        chmap.put(11, "Fourth");
  
        // 在ConcurrentSkipListMap上创建一个Iterator
        Iterator<ConcurrentSkipListMap
                     .Entry<Integer, String> > itr
            = chmap.entrySet().iterator();
  
        // 使用hasNext()方法来检查下一个元素是否存在。使用next()方法来检索下一个元素。
        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) 尝试为指定的键及其当前映射值(如果没有当前映射,则为null)计算映射。
computeIfAbsent​(K key, Function<? super K,? extends V> mappingFunction) 如果指定的键尚未与值相关联(即映射到null),则尝试使用给定的映射函数计算其值,并将其输入到此映射中,除非为null。
computeIfPresent​(K key, BiFunction<? super K,? super V,? extends V> remappingFunction) 如果指定键的值存在且非null,则尝试计算给定键及其当前映射值的新映射。
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) 如果指定键尚未关联到值或关联到null,则将其与给定的非null值关联。
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继承的方法

方法 | 描述
—|—
clear​() | 从该映射中删除所有映射(可选操作)。
containsKey​(Object key) | 如果此映射包含指定键的映射,则返回true。
containsValue​(Object value) | 如果该映射将一个或多个键映射到指定值,则返回true。
entry​(K k, V v) | 返回包含给定键和值的不可变的Map.Entry。
entrySet​() | 返回此映射中包含的映射的Set视图。
equals​(Object o) | 将指定对象与此映射进行比较以实现相等性。
get​(Object key) | 返回指定键所映射的值;如果此映射不包含此键的映射,则返回null。
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​() | 返回此映射中键值对映射的数量。
size​() | 返回此映射中的键值对数量。
参考资料: https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/util/concurrent/ConcurrentMap.html

Python教程

Java教程

Web教程

数据库教程

图形图像教程

大数据教程

开发工具教程

计算机教程