Java ConcurrentSkipListSet
Java中的ConcurrentSkipListSet就像TreeSet一样是一个排序集,但它也是可伸缩的和并发的,因此ConcurrentSkipListSet是线程安全的,可以被多个线程安全访问。
在ConcurrentSkipListSet中,使用比较和交换(CAS)以原子方式完成添加和删除等操作。这些都是无锁的,因此不存在同步开销。
ConcurrentSkipListSet是在Java 6中添加的,它是java.util.concurrent包的一部分。
SkipList数据结构
根据https://en.wikipedia.org/wiki/Skip_list –跳过列表是一种数据结构,可以在有序元素序列中进行快速搜索。通过维护子序列的链接层次结构,使快速搜索成为可能,每个连续的子序列跳过的元素比上一个要少。
如我们所见,为了更快地进行搜索,跳过列表要求元素按有序顺序排列,这就是为什么在Java ConcurrentSkipListSet中对元素进行排序的原因。
Java ConcurrentSkipListSet –排序集
Java中的ConcurrentSkipListSet类实现NavigableSet接口,该接口又扩展了SortedSet接口。因此,ConcurrentSkipListSet是一个排序集合,其导航方法报告给定搜索目标的最接近匹配项。
ConcurrentSkipListSet的元素根据其自然顺序或者在集合创建时提供的Comparator保持排序,具体取决于使用哪个构造函数。
ConcurrentSkipListSet内部数据结构
就像其他Set实现使用等效的Map实现存储元素一样,ConcurrentSkipListSet也在内部使用ConcurrentSkipListMap。每个ConcurrentSkipListSet构造函数都创建一个ConcurrentSkipListMap实例,并将其用于其操作。
Java ConcurrentSkipListSet构造函数
ConcurrentSkipListSet()–构造一个新的空集合,该集合根据其自然顺序对其元素进行排序。
ConcurrentSkipListSet(Collection <?extends E> c)–构造一个包含指定集合中元素的新集合,该集合根据其自然顺序对其元素进行排序。
ConcurrentSkipListSet(Comparator <?super E>比较器)–构造一个新的空集,该空集根据指定的比较器对其元素进行排序。
ConcurrentSkipListSet(SortedSet s)–构造一个新集合,该集合包含与指定的排序集合相同的元素,并使用相同的顺序。
ConcurrentSkipListSet Java示例
import java.util.Iterator; import java.util.NavigableSet; import java.util.concurrent.ConcurrentSkipListSet; public class SkipSetDemo { public static void main(String[] args) { NavigableSet<String> carSet = new ConcurrentSkipListSet<String>(); carSet.add("Audi"); carSet.add("Jaguar"); carSet.add("BMW"); carSet.add("Mini Cooper"); carSet.add("BMW"); Iterator<String> itr = carSet.iterator(); while(itr.hasNext()){ System.out.println("Value - " + itr.next()); } } }
输出:
Value - Audi Value - BMW Value - Jaguar Value - Mini Cooper
这里要注意的几件事
元素按排序顺序存储。
即使" BMW"添加了两次,也只能插入一次,但作为Set实现的ConcurrentSkipListSet不允许重复的元素。
ConcurrentSkipListSet中不允许为空
Java中的ConcurrentSkipListSet不允许使用空值。
如果添加语句carSet.add(null);在前面的示例中,将导致以下错误。
Exception in thread "main" java.lang.NullPointerException at java.base/java.util.concurrent.ConcurrentSkipListMap.doPut(ConcurrentSkipListMap.java:597) at java.base/java.util.concurrent.ConcurrentSkipListMap.putIfAbsent(ConcurrentSkipListMap.java:1788) at java.base/java.util.concurrent.ConcurrentSkipListSet.add(ConcurrentSkipListSet.java:242) at com.theitroad.SkipSetDemo.main(SkipSetDemo.java:14)
ConcurrentSkipListSet示例中的导航方法
由于ConcurrentSkipListSet实现了NavigableSet接口,因此它具有报告给定搜索目标最接近匹配项的导航方法。在这里,我们有一个示例,显示了一些导航方法。
public class SkipSetDemo { public static void main(String[] args) { NavigableSet<Integer> numSet = new ConcurrentSkipListSet<Integer>(); numSet.add(1); numSet.add(2); numSet.add(5); numSet.add(8); numSet.add(10); numSet.add(16); System.out.println("** Ceiling method Example **"); //Returns the least element in this set greater than or equal to the //given element int num = numSet.ceiling(9); System.out.println("num- " + num); System.out.println("** Floor method Example **"); //Returns the greatest element in this set less than or equal to the //given element num = numSet.floor(9); System.out.println("num- " + num); System.out.println("** Lower method Example **"); //Returns the greatest element in this set strictly less than the given element num = numSet.lower(10); System.out.println("num- " + num); } }
输出:
** Ceiling method Example ** num- 10 ** Floor method Example ** num- 8 ** Lower method Example ** num- 8