java.util.concurrent.ConcurrentNavigableMap接口是为了支持NavigableMap并发访问的而设计的子接口,使其子类可以实现并发访问。该接口继承自ConcurrentMap及NavigableMap接口,支持NavigableMap操作,并且递归地支持其可导航的子映射和近似匹配。既保证了线程安全性,又提供导航搜索子Map视图的功能。可以通过不同的方法,如 headMap(), subMap() 和tailMap(),返回这些子类。
java.util.concurrent.ConcurrentMap接口是Map接口的子接口,支持底层Map变量上的原子操作。 它具有获取和设置方法,如在变量上的读取和写入。 也就是说,一个集合与同一变量上的任何后续读取相关联。 该接口确保线程安全性和原子性保证。
NavigableMap 扩展了 SortedMap 接口,具有了针对给定搜索目标返回最接近匹配项的导航方法。
SortedMap(java.util.SortedMap)接口是Map的子接口,SortedMap中增加了元素的排序功能。可以使用Comparator的实现作为TreeMap 构造函数的参数 ,这个Comparator将用于对存储在SortedMap中的键、值对的键进行排序。
1、相关接口介绍
1.1 SortedMap方法
//可以自定义排序比较器
Comparator<? super K> comparator();
//按key升序排列,返回子映射,fromKey到toKey,包括fromKey,不包括toKey
SortedMap<K,V> subMap(K fromKey, K toKey);
//按key升序排列,返回子映射,开头到toKey,不包括toKey
SortedMap<K,V> headMap(K toKey);
//按key升序排列,返回子映射,fromKey到末尾,包括fromKey
SortedMap<K,V> tailMap(K fromKey);
//按key升序排列,返回第一个key
K firstKey();
//按key升序排列,返回最后一个key
K lastKey();
//返回key的集合,升序排列
Set<K> keySet();
//返回value的集合,按key升序排列,
Collection<V> values();
//返回Entry的集合,按key升序排列
Set<Map.Entry<K, V>> entrySet();
1.2 NavigableMap方法
NavigableMap继承了SortedMap:
public interface NavigableMap<K,V> extends SortedMap<K,V>
定义了一些导航方法:
// 找到第一个比指定的key小的值
Map.Entry<K,V> lowerEntry(K key);
// 找到第一个比指定的key小的key
K lowerKey(K key);
// 找到第一个小于或等于指定key的值
Map.Entry<K,V> floorEntry(K key);
// 找到第一个小于或等于指定key的key
K floorKey(K key);
// 找到第一个大于或等于指定key的值
Map.Entry<K,V> ceilingEntry(K key);
//找到第一个大于或等于指定key的key
K ceilingKey(K key);
// 找到第一个大于指定key的值
Map.Entry<K,V> higherEntry(K key);
// 找到第一个大于指定key的key
K higherKey(K key);
// 获取最小值
Map.Entry<K,V> firstEntry();
// 获取最大值
Map.Entry<K,V> lastEntry();
// 删除最小的元素
Map.Entry<K,V> pollFirstEntry();
// 删除最大的元素
Map.Entry<K,V> pollLastEntry();
//返回key降序排列的NavigableMap(视图),注意是视图,所以对它进行一个remove操作,也会影响到原来的Map的,是同一个引用
NavigableMap<K,V> descendingMap();
// 返回一个Navigable的key的集合,NavigableSet和NavigableMap类似(返回key升序排列的NavigableSet)
NavigableSet<K> navigableKeySet();
// 对上述集合倒序(返回key降序排列的NavigableSet)
NavigableSet<K> descendingKeySet();
//返回key升序排列的子映射,设置包含标志
NavigableMap<K,V> subMap(K fromKey, boolean fromInclusive, K toKey, boolean toInclusive);
//按key升序排列,返回子映射,开头到toKey,设置包含标志
NavigableMap<K,V> headMap(K toKey, boolean inclusive);
//按key升序排列,返回子映射,fromKey到末尾,设置包含标志
NavigableMap<K,V> tailMap(K fromKey, boolean inclusive);
//同时也继承了SortedMap的【不带包含标志】的子映射方法
SortedMap<K,V> subMap(K fromKey, K toKey);
SortedMap<K,V> headMap(K toKey);
SortedMap<K,V> tailMap(K fromKey);
1.3 ConcurrentNavigableMap方法
从定义上看,ConcurrentNavigableMap继承了NavigableMap和ConcurrentMap,就是两者功能的结合,既保证线程安全性,又提供导航搜索子Map视图的功能。ConcurrentNavigableMap中定义的方法也很简单,跟NavigableMap中的方法类似,只不过NavigableMap中返回的子Map视图是NavigableMap类型,而在ConcurrentNavigableMap中返回的都是ConcurrentNavigableMap类型。
// 返回此映射部分的视图,其键的范围从fromKey到toKey。
ConcurrentNavigableMap《K,V》 subMap(K fromKey, boolean fromInclusive, K toKey, boolean toInclusive)
// 返回此映射部分的视图,其键的范围从fromKey(包含)到toKey(不包括)。
ConcurrentNavigableMap《K,V》 subMap(K fromKey, K toKey)
// 返回此映射部分的视图,其键严格小于toKey。
ConcurrentNavigableMap《K,V》 headMap(K toKey)
// 返回此映射的部分视图,其键小于(或等于,如果包含为true)toKey。
ConcurrentNavigableMap《K,V》 headMap(K toKey, boolean inclusive)
// 返回此映射的部分视图,其键大于或等于fromKey。
ConcurrentNavigableMap《K,V》 tailMap(K fromKey)
// 返回此映射部分的视图,其键大于(或等于,如果inclusive为true)fromKey。
ConcurrentNavigableMap《K,V》 tailMap(K fromKey, boolean inclusive)
// 返回此映射中包含的映射的逆序视图。
ConcurrentNavigableMap《K,V》 descendingMap()
// 返回此映射中包含的键的NavigableSet视图。
NavigableSet《K》 navigableKeySet()
// 返回此映射中包含的键的NavigableSet视图。
NavigableSet《K》 keySet()
// 返回此映射中包含的键的反向顺序NavigableSet视图。
NavigableSet《K》 descendingKeySet()
2、重点方法介绍
2.1 headMap()
headMap(T toKey)方法会返回一个key值小于给定的值的一个map集合。如果改变初始集合,这个改动也会映射到headMap中。示例如下:
import static org.junit.jupiter.api.Assertions.*;
import java.util.concurrent.ConcurrentNavigableMap;
import java.util.concurrent.ConcurrentSkipListMap;
import org.junit.jupiter.api.Test;
class ConcurrentNavigableMapTest {
@Test
void test() {
ConcurrentNavigableMap map = new ConcurrentSkipListMap();
map.put("1", "one");
map.put("2", "two");
map.put("3", "three");
ConcurrentNavigableMap headMap = map.headMap("2");
Set<String> keySet = headMap.keySet();
for(String key : keySet) {
System.out.println("key:" + key +" , value:" + headMap.get(key));
}
}
}
程序运行结果
headMap将指向只包含key为1的ConcurrentNavigableMap, 因为只有这个键严格小于“2”。
key:1 , value:one
2.2 tailMap()
tailMap(T fromKey) 方法返回一个key值大于和等于给定的值的一个map集合。如果改变初始集合,这个改动也会映射到tailMap中。示例如下:
import static org.junit.jupiter.api.Assertions.*;
import java.util.Set;
import java.util.concurrent.ConcurrentNavigableMap;
import java.util.concurrent.ConcurrentSkipListMap;
import org.junit.jupiter.api.Test;
class ConcurrentNavigableMapTest {
@Test
void test() {
ConcurrentNavigableMap map = new ConcurrentSkipListMap();
map.put("1", "one");
map.put("2", "two");
map.put("3", "three");
ConcurrentNavigableMap headMap = map.tailMap("2");
Set<String> keySet = headMap.keySet();
for(String key : keySet) {
System.out.println("key:" + key +" , value:" + headMap.get(key));
}
}
}
程序运行结果
tailMap包含了 keys “2” 和"3" ,因为这两个key大于等于给定的key”2”。
key:2 , value:two
key:3 , value:three
2.3 subMap()
subMap(K fromKey, K toKey)方法返回一个参数中从fromKey(包含)到tokey(不包含)的部分集合。示例如下:
import static org.junit.jupiter.api.Assertions.*;
import java.util.Set;
import java.util.concurrent.ConcurrentNavigableMap;
import java.util.concurrent.ConcurrentSkipListMap;
import org.junit.jupiter.api.Test;
class ConcurrentNavigableMapTest {
@Test
void test() {
ConcurrentNavigableMap map = new ConcurrentSkipListMap();
map.put("1", "one");
map.put("2", "two");
map.put("3", "three");
ConcurrentNavigableMap headMap = map.subMap("2", "3");
Set<String> keySet = headMap.keySet();
for(String key : keySet) {
System.out.println("key:" + key +" , value:" + headMap.get(key));
}
}
}
程序运行结果
返回的submap contains 只有 key为"2", 因为大于等于 “2” 小于 “3”。
key:2 , value:two
3、代码示例
3.1 ConcurrentNavigableMap示例1
import java.util.concurrent.ConcurrentNavigableMap;
import java.util.concurrent.ConcurrentSkipListMap;
public class TestThread {
public static void main(final String[] arguments) {
ConcurrentNavigableMap<String,String> map =
new ConcurrentSkipListMap<String, String>();
map.put("1", "One");
map.put("2", "Two");
map.put("3", "Three");
map.put("5", "Five");
map.put("6", "Six");
System.out.println("Initial ConcurrentHashMap: "+map);
System.out.println("HeadMap(\"2\") of ConcurrentHashMap: "+map.headMap("2"));
System.out.println("TailMap(\"2\") of ConcurrentHashMap: "+map.tailMap("2"));
System.out.println(
"SubMap(\"2\", \"4\") of ConcurrentHashMap: "+map.subMap("2","4"));
}
}
程序执行结果
Initial ConcurrentHashMap: {1 = One, 2 = Two, 3 = Three, 5 = Five, 6 = Six}
HeadMap("2") of ConcurrentHashMap: {1 = One}
TailMap("2") of ConcurrentHashMap: {2 = Two, 3 = Three, 5 = Five, 6 = Six}
SubMap("2", "4") of ConcurrentHashMap: {2 = Two, 3 = Three}
3.2 ConcurrentNavigableMap示例2
ConcurrentNavigableMap<Integer, String> concurrentNavigableMap = new ConcurrentSkipListMap();
concurrentNavigableMap.put(1, "张三");
concurrentNavigableMap.put(2, "李四");
concurrentNavigableMap.put(3, "王五");
concurrentNavigableMap.put(4, "赵六");
//取key 1 - 4 之间的值 包头不报尾
ConcurrentNavigableMap<Integer, String> subMap = concurrentNavigableMap.subMap(1, 4);
System.out.println(JSON.toJSONString(subMap));
//取传入key之前值
ConcurrentNavigableMap<Integer, String> tailMap = concurrentNavigableMap.tailMap(2);
System.out.println(JSON.toJSONString(tailMap));
//取传入key之后的值
ConcurrentNavigableMap<Integer, String> headMap = concurrentNavigableMap.headMap(3);
System.out.println(JSON.toJSONString(headMap));
//倒叙获取所有的key
NavigableSet<Integer> navigableSet = concurrentNavigableMap.descendingKeySet();
System.out.println(JSON.toJSONString(navigableSet));
//正序获取所有的key
NavigableSet<Integer> navigableKeySet = concurrentNavigableMap.navigableKeySet();
System.out.println(JSON.toJSONString(navigableKeySet));
//倒叙获取整个map
ConcurrentNavigableMap<Integer, String> descendingMap = concurrentNavigableMap.descendingMap();
System.out.println(JSON.toJSONString(descendingMap));
//获取指定key 的一个map
Map.Entry<Integer, String> ceilingEntry = concurrentNavigableMap.ceilingEntry(4);
System.out.println(JSON.toJSONString(ceilingEntry));
//获取指定key 的一个key
Integer ceilingKey = concurrentNavigableMap.ceilingKey(4);
System.out.println(JSON.toJSONString(ceilingKey));
//与ceilingEntry 似乎对等
Map.Entry<Integer, String> floorEntry = concurrentNavigableMap.floorEntry(4);
System.out.println(JSON.toJSONString(floorEntry));
//取比当前key大一个的map值
Map.Entry<Integer, String> higherEntry = concurrentNavigableMap.higherEntry(2);
System.out.println(JSON.toJSONString(higherEntry));
//取比当前key小一个的map值
Map.Entry<Integer, String> lowerEntry = concurrentNavigableMap.lowerEntry(2);
System.out.println(JSON.toJSONString(lowerEntry));
//取最后一个map值
Map.Entry<Integer, String> lastEntry = concurrentNavigableMap.lastEntry();
System.out.println(JSON.toJSONString(lastEntry));
//删除并返回与此映射中最小键关联的键值映射,如果映射为空,则返回null
/** Map.Entry<Integer, String> firstEntry = concurrentNavigableMap.pollFirstEntry();
System.out.println(JSON.toJSONString(firstEntry));
System.out.println(JSON.toJSONString(concurrentNavigableMap));*/
//删除并返回与此映射中最大键关联的键值映射,如果映射为空,则返回 {@code null}。 @return 移除
/*Map.Entry<Integer, String> pollLastEntry = concurrentNavigableMap.pollLastEntry();*/
//可对响应的value 做计算
/*String compute = concurrentNavigableMap.compute(2, new BiFunction<Integer, String, String>() {
@Override
public String apply(Integer integer, String s) {
return integer + ":BiFunction";
}
});
System.out.println(compute);*/
//如果key 存在 返回原來的值 不存在返回 "99999999"
String computeIfAbsent = concurrentNavigableMap.computeIfAbsent(100, new Function<Integer, String>() {
@Override
public String apply(Integer integer) {
return "99999999";
}
});
System.out.println(computeIfAbsent);
//可以拼接map中的key和value
String computeIfPresent = concurrentNavigableMap.computeIfPresent(2, new BiFunction<Integer, String, String>() {
@Override
public String apply(Integer integer, String s) {
return integer + "=======" + s;
}
});
System.out.println(computeIfPresent);
}
3.3 NavigableMap示例
public static void main(String[] args) {
// NavigableMap多态接收TreeMap的实例
NavigableMap<String, Integer> navigatorTreeMap = new TreeMap<String, Integer>() {{
put("aa", 11);
put("bb", 22);
put("cc", 33);
put("dd", 44);
put("ee", 55);
put("ff", 55);
put("gg", 55);
}};
System.out.println(navigatorTreeMap.size());// 7个元素:7
System.out.println(navigatorTreeMap.ceilingKey("cc"));// 返回大于等于cc的最小键:cc
System.out.println(navigatorTreeMap.ceilingEntry("c"));// 返回一个键-值映射关系,它与大于等于cc的最小键关联:cc=33
System.out.println(navigatorTreeMap.firstKey());// 最小键:aa
System.out.println(navigatorTreeMap.firstEntry());// 最小键对应的k-v键值对:aa=11
System.out.println(navigatorTreeMap.floorEntry("c"));// 返回一个键-值映射关系,它与小于等于给定键的最大键关联:bb=22
System.out.println(navigatorTreeMap.floorKey("cc"));// 返回小于等于cc的最大键:cc
System.out.println(navigatorTreeMap.headMap("bb"));// 返回此映射的部分视图,其键值严格小于bb:{aa=11}
System.out.println(navigatorTreeMap.headMap("bb", true));// 同上小于等于(true):{aa=11, bb=22}
System.out.println(navigatorTreeMap.higherEntry("c"));// 返回一个键-值映射关系,它与小于等于给定键的最大键关联:cc=33
System.out.println(navigatorTreeMap.higherKey("cc"));// 返回小于等于cc的最大键:dd
System.out.println(navigatorTreeMap.lastEntry());// 返回一个键-值映射关系,它与小于等于给定键的最大键关联:gg=55
System.out.println(navigatorTreeMap.lastKey());// 返回小于等于cc的最大键:gg
System.out.println(navigatorTreeMap.lowerEntry("c"));// 返回一个键-值映射关系,它与小于等于给定键的最大键关联:bb=22
System.out.println(navigatorTreeMap.lowerKey("cc"));// 返回严格小于cc的最大键:bb
System.out.println(navigatorTreeMap.pollFirstEntry());// 移除并返回与此映射中的最小键关联的键-值映射关系:aa=11
System.out.println(navigatorTreeMap.pollLastEntry());// 移除并返回与此映射中的最大键关联的键-值映射关系:gg=55
System.out.println(navigatorTreeMap.navigableKeySet());// 返回此映射中所包含键的
// NavigableSet 视图。:[bb, cc, dd, ee, ff]
System.out.println(navigatorTreeMap.subMap("aa", true, "dd", true));// 返回部分视图,true表示包括当前元素键值对:{bb=22, cc=33, dd=44}
System.out.println(navigatorTreeMap.subMap("bb", "dd"));// 返回部分视图包括前面的元素,不包括后面的:{bb=22, cc=33}
System.out.println(navigatorTreeMap.tailMap("cc"));// 返回元素大于cc的元素映射视图,包括cc://{cc=33, dd=44, ee=55, ff=55}
System.out.println(navigatorTreeMap.tailMap("cc", false));// 返回元素大于等于cc的元素映射视图:{dd=44, ee=55, ff=55}
//逆序视图
NavigableMap<String, Integer> descendingMap = navigatorTreeMap.descendingMap();
System.out.println(navigatorTreeMap); //原来的Map:
System.out.println(descendingMap);// 返回逆序视图:{gg=55, ff=55, ee=55, dd=44, cc=33, bb=22, aa=11}
//执行一个移除操作后 再看看会不会影响到原来的Map
descendingMap.remove("gg");
System.out.println(navigatorTreeMap); //原来的Map:{aa=11, bb=22, cc=33, dd=44, ee=55, ff=55}
System.out.println(descendingMap);// 返回逆序视图:{ff=55, ee=55, dd=44, cc=33, bb=22, aa=11}
}
评论区