Java中的ConcurrentSkipListMap(附例子)
ConcurrentSkipListMap类 是Java Collections框架的一个成员,它在JDK 1.6中被引入,属于 java.util.concurrent 包。ConcurrentSkipListMap是ConcurrentNavigableMap的可伸缩实现。所有元素都是基于自然排序或构建时传递的比较器进行排序的。该类使用SkipList数据结构的并发变体,提供插入、删除、更新和访问操作的 log(n) 时间成本。这些操作可由多个线程同时执行,并且是安全的。
声明
public class ConcurrentSkipListMap<K,V> extends AbstractMap<K,V> implements ConcurrentNavigableMap<K,V>, Cloneable, Serializable
在这里, K 是键对象类型, V 是值对象类型。
ConcurrentSkipListMap的层次结构

它实现了 Serializable , Cloneable , ConcurrentMap<K,V>, ConcurrentNavigableMap<K,V>, Map<K,V>, NavigableMap<K,V>, SortedMap<K,V> 接口,并扩展了 AbstractMap <K,V>类。
ConcurrentSkipListMap的构造函数
1. ConcurrentSkipListMap() : 构造一个新的、空的、按键的自然排序排序的映射。
ConcurrentSkipListMap<K, V> cslm = new ConcurrentSkipListMap<K, V>();
**2. ConcurrentSkipListMap(Comparator <? super K> comparator) ** : 构造一个新的、空的、根据指定比较器排序的映射。
ConcurrentSkipListMap<K, V> cslm = new ConcurrentSkipListMap<K, V>(Comparator<? super K> comparator);
**3. ConcurrentSkipListMap(Map <? extends K,? extends V> m) ** : 构造一个新的映射,其中包含与给定映射相同的映射关系,并按键的自然排序进行排序。
ConcurrentSkipListMap<K, V> cslm = new ConcurrentSkipListMap<K, V>(Map<? extends K,? extends V> m);
**4. ConcurrentSkipListMap(SortedMap <K,? extends V> m) ** : 构造一个新的映射,其中包含与指定排序映射相同的映射关系。
ConcurrentSkipListMap<K, V> cslm = new ConcurrentSkipListMap<K, V>(SortedMap<K,? extends V> m);
示例
// Java程序演示
// ConcurrentSkipListMap
import java.io.*;
import java.util.*;
import java.util.concurrent.*;
class ConcurrentSkipListMapExample {
public static void main(String[] args)
{
// 创建ConcurrentSkipListMap实例
ConcurrentSkipListMap<String, String> cslm
= new ConcurrentSkipListMap<String, String>();
// 使用put方法添加映射关系
cslm.put("3", "Geeks");
cslm.put("2", "from");
cslm.put("1", "Hi!");
cslm.put("5", "Geeks");
cslm.put("4", "for");
// 打印到控制台
System.out.println("初始化Map : " + cslm);
// 打印键为大于2的键值对
System.out.println("ceilingEntry-2: "
+ cslm.ceilingEntry("2"));
// 获取键集的倒序
NavigableSet navigableSet = cslm.descendingKeySet();
System.out.println("descendingKeySet: ");
// 遍历键集
Iterator itr = navigableSet.iterator();
while (itr.hasNext()) {
String s = (String)itr.next();
System.out.println(s);
}
// 打印第一个映射
System.out.println("firstEntry: "
+ cslm.firstEntry());
// 打印最后一个映射
System.out.println("lastEntry: "
+ cslm.lastEntry());
// 移除第一个映射并打印
System.out.println("pollFirstEntry: "
+ cslm.pollFirstEntry());
// 打印第一个映射
System.out.println("现在的第一个映射: "
+ cslm.firstEntry());
// 移除最后一个映射并打印
System.out.println("pollLastEntry: "
+ cslm.pollLastEntry());
// 打印最后一个映射
System.out.println("现在的最后一个映射: "
+ cslm.lastEntry());
}
}
输出
初始化Map : {1=Hi!, 2=from, 3=Geeks, 4=for, 5=Geeks}
ceilingEntry-2: 2=from
descendingKeySet:
5
4
3
2
1
firstEntry: 1=Hi!
lastEntry: 5=Geeks
pollFirstEntry: 1=Hi!
现在的第一个映射: 2=from
pollLastEntry: 5=Geeks
现在的最后一个映射: 4=for
基本操作
1. 添加映射
ConcurrentSkipListMap的put()方法将指定值与指定键在该Map中关联。如果Map先前包含该键的映射,则旧值将被替换。
// Java程序演示添加
// ConcurrentSkipListMap中的映射
import java.util.concurrent.*;
class AddingMappingsExample {
public static void main(String[] args)
{
// 初始化Map
ConcurrentSkipListMap<Integer, Integer> cslm
= new ConcurrentSkipListMap<Integer, Integer>();
// 向该Map添加元素
for (int i = 1; i <= 9; i++)
cslm.put(i, i);
// 对Map进行put()操作
System.out.println("在put()之后: " + cslm);
}
}
输出
在put()之后: {1=1, 2=2, 3=3, 4=4, 5=5, 6=6, 7=7, 8=8, 9=9}
2. 移除映射
ConcurrentSkipListMap的remove()方法从该Map中删除指定键的映射。如果该键没有映射,则返回null。执行该方法后,Map的大小会减小。要删除Map的第一个和最后一个条目,我们可以使用 pollFirstEntry() 和 pollLastEntry() 。
// Java Program Demonstrate removing
// mappings from ConcurrentSkipListMap
import java.util.concurrent.*;
class RemovingMappingsExample {
public static void main(String[] args)
{
// 初始化映射表
ConcurrentSkipListMap<Integer, Integer> cslm
= new ConcurrentSkipListMap<Integer, Integer>();
// 向映射表中添加元素
for (int i = 1; i <= 6; i++)
cslm.put(i, i);
// 移除映射表中的元素
cslm.remove(5);
// 打印修改后的映射表
System.out.println("After remove(): " + cslm);
// 移除映射表中第一个映射并打印
System.out.println("pollFirstEntry: "
+ cslm.pollFirstEntry());
// 移除映射表中最后一个映射并打印
System.out.println("pollLastEntry: "
+ cslm.pollLastEntry());
// 打印最终映射表
System.out.println("map contents: " + cslm);
}
}
输出
After remove(): {1=1, 2=2, 3=3, 4=4, 6=6}
pollFirstEntry: 1=1
pollLastEntry: 6=6
map contents: {2=2, 3=3, 4=4}
3. 迭代
我们可以使用迭代器接口遍历集合框架中的任何结构。由于迭代器使用一种类型的数据,我们使用Entry< ? , ? >将两种单独的类型解析为兼容的格式。然后使用next()方法打印ConcurrentSkipListMap的元素。
// Java Program to demonstrate iterating
// over ConcurrentSkipListMap
import java.util.concurrent.*;
import java.util.*;
class IteratingExample {
public static void main(String[] args)
{
// 创建ConcurrentSkipListMap的实例
ConcurrentSkipListMap<Integer, Integer> cslm
= new ConcurrentSkipListMap<>();
// 使用put方法添加映射
for (int i = 0; i < 6; i++) {
cslm.put(i, i);
}
// 创建一个ConcurrentSkipListMap上的迭代器
Iterator<ConcurrentSkipListMap
.Entry<Integer, Integer> > itr
= cslm.entrySet().iterator();
// hasNext()方法用于检查是否有下一个元素,next()方法用于检索下一个元素
while (itr.hasNext()) {
ConcurrentSkipListMap
.Entry<Integer, Integer> entry
= itr.next();
System.out.println("Key = " + entry.getKey()
+ ", Value = "
+ entry.getValue());
}
}
}
输出
Key = 0, Value = 0
Key = 1, Value = 1
Key = 2, Value = 2
Key = 3, Value = 3
Key = 4, Value = 4
Key = 5, Value = 5
ConcurrentSkipListMap的方法
| 方法 | 描述 |
|---|---|
| ceilingEntry(K key) | 返回与给定键大于或等于的最小键相关联的键值映射,如果没有这样的条目,则返回null。 |
| ceilingKey(K key) | 返回大于或等于给定键的最小键,如果没有这样的键,则返回null。 |
| clear() | 从此映射中删除所有映射。 |
| clone() | 返回此ConcurrentSkipListMap实例的浅表副本。 |
| compute(K key, BiFunction<? super K,? super V,? extends V> remappingFunction) | 尝试为指定的键和其当前映射的值(如果没有当前映射,则为null)计算映射。 |
| computeIfAbsent(K key, Function<? super K,? extends V> mappingFunction) | 如果指定的键尚未与值关联,则尝试使用给定的映射函数计算其值并将其输入到此映射中,除非为null。 |
| computeIfPresent(K key, BiFunction<? super K,? super V,? extends V> remappingFunction) | 如果存在指定键的值,则尝试根据键和其当前映射的值计算新映射。 |
| containsKey(Object key) | 如果此映射包含指定键的映射,则返回true。 |
| containsValue(Object value) | 如果此映射将一个或多个键映射到指定值,则返回true。 |
| entrySet() | 返回此映射中包含的映射的一个Set视图。 |
| equals(Object o) | 将指定的对象与此映射进行比较以判断相等性。 |
| firstEntry() | 返回此映射中的最小键所关联的键值映射,如果映射为空,则返回null。 |
| firstKey() | 返回此映射中当前第一个(最低)键。 |
| floorEntry(K key) | 返回与小于或等于给定键的最大键相关联的键值映射,如果没有这样的键,则返回null。 |
| floorKey(K key) | 返回小于或等于给定键的最大键,如果没有这样的键,则返回null。 |
| get(Object key) | 如果此映射包含该键的映射,则返回该键映射的值;否则返回null。 |
| getOrDefault(Object key, V defaultValue) | 如果此映射包含该键的映射,则返回该键映射的值;否则返回defaultValue。 |
| headMap(K toKey) | 返回其键严格小于 toKey 的此映射的一部分视图。 |
| headMap(K toKey, boolean inclusive) | 返回其键小于(或等于,如果inclusive为true)toKey的此映射的一部分视图。 |
| higherEntry(K key) | 返回与严格大于给定键的最小键相关联的键值映射,如果没有这样的键,则返回null。 |
| higherKey(K key) | 返回严格大于给定键的最小键,如果没有这样的键,则返回null。 |
| keySet() | 返回此映射中包含的键的NavigableSet视图。 |
| lastEntry() | 返回此映射中的最大键所关联的键值映射,如果映射为空,则返回null。 |
| lastKey() | 返回此映射中当前最后一个(最高)键。 |
| lowerEntry(K key) | 返回与小于给定键的最大键相关联的键值映射,如果没有这样的键,则返回null。 |
| lowerKey(K key) | 返回小于给定键的最大键,如果没有这样的键,则返回null。 |
| navigableKeySet() | 返回此映射中包含的键的NavigableSet视图。 |
| pollFirstEntry() | 移除并返回此映射中的第一个(最低)映射。 |
| pollLastEntry() | 移除并返回此映射中的最后一个(最高)映射。 |
| put(K key, V value) | 将指定值与此映射中的指定键关联。 |
| putAll(Map map) | 从指定映射中将所有映射复制到此映射中,这些映射将替换此映射中原来相应的键的映射。 |
| remove(Object key) | 如果存在此映射中的键的映射,则将其移除(可选操作)。 |
| replace(K key, V value) | 只有在映射当前将指定键映射到某个值时,才将其替换为指定值。 |
| replace(K key, V oldValue, V newValue) | 仅当当前将指定键映射到某个值时,才将其替换为另一个值。 |
| size() | 返回此映射中的键-值映射关系数。 |
| subMap(K fromKey, boolean fromInclusive, K toKey, boolean toInclusive) | 返回此映射部分的视图,该视图的键范围从fromKey到toKey。 |
| subMap(K fromKey, K toKey) | 返回其键范围从 fromKey(包括)到 toKey(不包括)的此映射的一部分视图。 |
| tailMap(K fromKey) | 返回其键大于或等于 fromKey 的此映射的部分视图。 |
| tailMap(K fromKey, boolean inclusive) | 返回其键大于(或等于,如果 inclusive为true)fromKey的此映射的一部分视图。 |
| values() | 返回此映射中包含的值的Collection视图。 |
| lastKey() | 返回当前地图中最后一个(最高值)键。 |
| lowerEntry(K key) | 返回与小于给定键的最大键关联的键值映射,如果没有这样的键,则返回null。 |
| lowerKey(K key) | 返回严格小于给定键的最大键,如果没有这样的键,则返回null。 |
| merge(K key, V value, BiFunction remappingFunction) | 如果指定的键尚未与值关联,则将其与给定值关联。 |
| pollFirstEntry() | 移除并返回键值映射,该映射与此地图中最小的键相关联,如果地图为空,则返回null。 |
| pollLastEntry() | 移除并返回与此地图中最大键相关联的键值映射,如果地图为空,则返回null。 |
| put(K key, V value) | 将指定的值与指定的键在此地图中关联。 |
| putIfAbsent(K key, V value) | 如果指定的键尚未关联到值,则将其与给定值关联。 |
| remove(Object key) | 如果存在,则从此地图中删除指定键的映射。 |
| remove(Object key, Object value) | 仅当当前映射到给定值时,才删除钥匙的条目。 |
| replace(K key, V value) | 仅当当前映射到某些值时,才替换钥匙的条目。 |
| replace(K key, V oldValue, V newValue) | 仅当当前映射到给定值时,才替换钥匙的条目。 |
| subMap(K fromKey, boolean fromInclusive, K toKey, boolean toInclusive) | 返回从fromKey到toKey键范围的地图部分的视图。 |
| subMap(K fromKey, K toKey) | 返回一个视图,该视图为此地图中键的范围从fromKey(包括)到toKey(不包括)的部分。 |
| tailMap(K fromKey) | 返回键大于或等于fromKey的地图部分的视图。 |
| tailMap(K fromKey, boolean inclusive) | 返回其键大于(如果inclusive为true,则相对于等于)fromKey的地图部分的视图。 |
| values() | 返回此地图中包含的值的Collection视图。 |
在类java.util.AbstractMap中声明的方法
| METHOD | DESCRIPTION |
|---|---|
| hashCode() | 返回此映射的哈希码值。 |
| isEmpty() | 如果此映射不包含键值映射,则返回true。 |
| putAll(Map<? extends K,? extends V> m) | 将指定映射中的所有映射复制到此映射中(可选操作)。 |
| size() | 返回此映射中的键值映射数。 |
| toString() | 返回此映射的字符串表示形式。 |
在接口java.util.concurrent.ConcurrentMap中声明的方法
| METHOD | DESCRIPTION |
|---|---|
| forEach(BiConsumer<? super K,? super V> action) | 对此映射中的每个条目执行给定操作,直到处理完所有条目或操作引发异常。 |
| replaceAll(BiFunction<? super K,? super V,? extends V> function) | 用调用该条目上的给定函数的结果替换每个条目的值,直到处理完所有条目或函数引发异常。 |
在接口java.util.concurrent.ConcurrentNavigableMap中声明的方法
| METHOD | DESCRIPTION |
|---|---|
| descendingKeySet() | 返回此映射中包含的键的逆序NavigableSet视图。 |
| descendingMap() | 返回此映射中包含的映射的逆序视图。 |
| navigableKeySet() | 返回此映射中包含的键的NavigableSet视图。 |
在接口java.util.Map中声明的方法
| METHOD | DESCRIPTION |
|---|---|
| hashCode() | 返回此映射的哈希码值。 |
| isEmpty() | 如果此映射不包含键值映射,则返回true。 |
| putAll(Map<? extends K,? extends V> m) | 将指定映射中的所有映射复制到此映射中(可选操作)。 |
| size() | 返回此映射中的键值映射数。 |
在接口java.util.SortedMap中声明的方法
| METHOD | DESCRIPTION |
|---|---|
| comparator() | 返回用于按键排序的比较器,在这个映射中使用其键的自然排序时返回null。 |
参考: https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/util/concurrent/ConcurrentSkipListMap.html
极客教程