Java中的NavigableSet及示例
Java中的NavigableSet是一个接口,继承自SortedSet,用于实现可导航的Set。它具有SortedSet所拥有的一些功能,比如能够自动进行排序、去重等,同时还具备一些额外的功能,比如顺序遍历元素、获取特定区间内的元素等。
NavigableSet的继承关系
先来看一下NavigableSet的继承关系:
public interface NavigableSet<E> extends SortedSet<E> {
E lower(E e);
E floor(E e);
E ceiling(E e);
E higher(E e);
E pollFirst();
E pollLast();
Iterator<E> iterator();
NavigableSet<E> descendingSet();
Iterator<E> descendingIterator();
NavigableSet<E> subSet(E fromElement, boolean fromInclusive,
E toElement, boolean toInclusive);
NavigableSet<E> headSet(E toElement, boolean inclusive);
NavigableSet<E> tailSet(E fromElement, boolean inclusive);
SortedSet<E> subSet(E fromElement, E toElement);
SortedSet<E> headSet(E toElement);
SortedSet<E> tailSet(E fromElement);
...
}
在接口中,我们发现了许多新的方法,比如lower、floor、ceiling、higher等,这些方法都是用于定位NavigableSet中某个元素的位置的,可以方便地获取某个元素的前驱和后继,或者获取某个区间内的元素。
NavigableSet的实现类
Java中提供了三个NavigableSet的实现类:TreeSet、ConcurrentSkipListSet和SubSet。其中TreeSet是最基础的实现,它内部使用了一棵树来实现NavigableSet的所有功能。ConcurrentSkipListSet是一个线程安全的NavigableSet实现类,它对TreeSet进行了改进,解决了TreeSet在多线程环境下可能会出现的线程安全问题。SubSet则是一个SubsetView类型的NavigableSet,它不能直接被实例化,只能通过调用集合的subSet方法来获得。
TreeSet
TreeSet是一种有序的、基于红黑树实现的集合,它是SortedSet接口的实现类,同时也实现了NavigableSet接口。它的默认构造函数创建的集合是以自然顺序进行排序的。我们来看一下TreeSet的用法:
import java.util.TreeSet;
public class TreeSetExample {
public static void main(String[] args) {
TreeSet<String> set = new TreeSet<String>();
set.add("A");
set.add("B");
set.add("C");
set.add("D");
set.add("E");
System.out.println("Initial set: " + set);
// Using ceiling method
System.out.println("TreeSet using ceiling: " + set.ceiling("C"));
// Using higher method
System.out.println("TreeSet using higher: " + set.higher("C"));
// Using floor method
System.out.println("TreeSet using floor: " + set.floor("C"));
// Using lower method
System.out.println("TreeSet using lower: " + set.lower("C"));
// Using pollFirst method
System.out.println("TreeSet using pollFirst: " + set.pollFirst());
// Using pollLast method
System.out.println("TreeSet using pollLast: " + set.pollLast());
System.out.println("Final set: " + set);
}
}
在上述代码中,我们创建了一个TreeSet集合,并添加了一些元素。注意,我们添加的元素没有按照字母顺序进行排序,但我们最终输出的结果却是有序的,这是因为TreeSet内部自动进行了排序。然后我们使用了一些NavigableSet接口中的方法来进行遍历并获取集合中的元素,具体使用细节见注释。
ConcurrentSkipListSet
ConcurrentSkipListSet是一种线程安全、基于跳跃表的实现方式,它也实现了NavigableSet接口。与TreeSet相比,它具有更好的并发性能。我们来看一下ConcurrentSkipListSet的用法:
import java.util.concurrent.ConcurrentSkipListSet;
public class ConcurrentSkipListSetExample {
public static void main(String[] args) {
ConcurrentSkipListSet<String> set = new ConcurrentSkipListSet<String>();
set.add("A");
set.add("B");
set.add("C");
set.add("D");
set.add("E");
System.out.println("Initial set: " + set);
// Using ceiling method
System.out.println("ConcurrentSkipListSet using ceiling: " + set.ceiling("C"));
// Using higher method
System.out.println("ConcurrentSkipListSet using higher: " + set.higher("C"));
// Using floor method
System.out.println("ConcurrentSkipListSet using floor: " + set.floor("C"));
// Using lower method
System.out.println("ConcurrentSkipListSet using lower: " + set.lower("C"));
// Using pollFirst method
System.out.println("ConcurrentSkipListSet using pollFirst: " + set.pollFirst());
// Using pollLast method
System.out.println("ConcurrentSkipListSet using pollLast: " + set.pollLast());
System.out.println("Final set: " + set);
}
}
在上述代码中,我们创建了一个ConcurrentSkipListSet集合,并添加了一些元素。注意,ConcurrentSkipListSet也会自动进行排序,因此最终结果是有序的。我们使用了与TreeSet相同的NavigableSet接口中的方法,并且没有在多线程环境下创建此集合。如果我们在实际应用中需要在多线程环境下使用此集合,需要注意线程安全的问题。
SubSet
SubSet是NavigableSet的一个子集视图,在NavigableSet中使用subSet(fromElement, toElement)、subSet(fromElement, fromInclusive, toElement, toInclusive)等方法可以获得视图。
import java.util.NavigableSet;
import java.util.TreeSet;
public class NavigableSetExample {
public static void main(String[] args) {
TreeSet<Integer> set = new TreeSet<Integer>();
set.add(1);
set.add(2);
set.add(3);
set.add(4);
set.add(5);
System.out.println("Initial set: " + set);
// Get sub set
NavigableSet<Integer> subSet = set.subSet(2, true, 4, true);
System.out.println("Sub set: " + subSet);
// Using lower method
System.out.println("NavigableSet using lower: " + subSet.lower(3));
// Using higher method
System.out.println("NavigableSet using higher: " + subSet.higher(3));
}
}
在上述代码中,我们创建了一个TreeSet集合,并添加了一些整数元素。使用subSet方法获得了该集合的子集视图,在子集视图中使用了lower和higher方法获取前驱和后继。
结论
NavigableSet是Java中一个非常有用的集合接口,它具有SortedSet所有的功能,并且能够进行顺序遍历元素、获取特定区间内元素等操作。我们可以使用它的几种实现类来实现我们的功能需求,比较常用的是TreeSet和ConcurrentSkipListSet。如果需要获取集合的子集视图,可以使用subSet方法来获得该视图。使用NavigableSet能够方便地处理集合中的元素,并且大大提高开发效率。