Java ConcurrentSkipListSet

时间:2020-01-09 10:35:09  来源:igfitidea点击:

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