JDK
版本:AdoptOpenJDK 11.0.10+9
1 基本概念
ConcurrentSkipListMap
是在JDK 1.6
中新增的,为了对高并发场景下的有序Map
提供更好的支持,它有几个特点:
- 高并发场景
key
是有序的- 添加、删除、查找操作都是基于跳表结构(
Skip List
)实现的 key
和value
都不能为null
2 跳表(Skip List)
跳表(
Skip List
)是一种类似于链表的数据结构,其查询、插入、删除的时间复杂度都是O(logn)
。
在传统的单链表结构中,查找某个元素需要从链表的头部按顺序遍历,直到找到目标元素为止,查找的时间复杂度为O(n)
。
而跳表结合了树和链表的特点,其特性如下:
- 跳表由很多层组成;
- 每一层都是一个有序的链表;
- 最底层的链表包含所有元素;
- 对于每一层的任意一个节点,不仅有指向其下一个节点的指针,也有指向其下一层的指针;
- 如果一个元素出现在
Level n
层的链表中,则它在Level n
层以下的链表也都会出现。
Skip List
例子:
下图是一种可能的跳表结构:
如图,[1]
和[40]
节点有3
层,[8]
和[18]
节点有2
层。每一层都是有序的链表。
如果要查找目标节点[15]
,大致过程如下:
- 首先查看
[1]
节点的第1
层,发现[1]
节点的下一个节点为[40]
,大于15
,那么查找[1]
节点的下一层; - 查找
[1]
节点的第2
层,发现[1]
节点的下一个节点为[8]
,小于15
,接着查看下一个节点,发现下一个节点是[18]
,大于15
,因此查找[8]
节点的下一层; - 查找
[8]
节点的第2
层,发现[8]
节点的下一个节点是[10]
,小于15
,接着查看下一个节点[13]
,小于15
,接着查看下一个节点[15]
,发现其值等于15
,因此找到了目标节点,结束查询。
跳表实际上是一种 空间换时间 的数据结构。
3 ConcurrentSkipListMap结构
ConcurrentSkipListMap
用到了两种结构的节点。
Node
节点代表了真正存储数据的节点,包含了key
、value
、指向下一个节点的指针next
:
static