TreeSet是一个使用你较少的一个Set容器,很多同学可能不知道它是干嘛的,它和HashSet有什么区别,它底层是如何实现的?本篇文章带你全面了解掌握TreeSet
我们知道HashSet是没有顺序的,而TreeSet最大的特点就是一个有顺序的去重集合容器。
以上是TreeSet的类结构图:
说明: 构造一个空的有序set集合
说明:构造一个传入排序规则的有序Set集合
说明:构造一个集合元素为c的有序Set集合
Set接口的相关方法不做过多介绍,这边重点介绍下NavigableSet相关的方法。
说明: 返回TreeSet的顺序排列的迭代器。因为TreeSet时TreeMap实现的,所以这里实际上时返回TreeMap的“键集”对应的迭代器。
返回TreeSet的逆序排列的迭代器。因为TreeSet时TreeMap实现的,所以这里实际上时返回TreeMap的“键集”对应的迭代器。
说明:返回TreeSet的大小
说明:返回TreeSet是否为空
说明:返回TreeSet是否包含对象(o)
说明:添加e到TreeSet中
说明:删除TreeSet中的对象o
说明:清空TreeSet
说明:将集合c中的全部元素添加到TreeSet中
E toElement, boolean toInclusive)
说明:返回子Set,实际上是通过TreeMap的subMap()实现的。
说明:返回Set的头部,范围是:从头部到toElement,inclusive是是否包含toElement的标志。
说明:返回Set的尾部,范围是:从fromElement到结尾,inclusive是是否包含fromElement的标志。
说明:返回子Set。范围是:从fromElement(包括)到toElement(不包括)。
说明:返回Set的头部,范围是:从头部到toElement(不包括)。
说明:返回Set的尾部,范围是:从fromElement到结尾(不包括)。
说明:返回Set的比较器
说明:返回Set的第一个元素
说明:返回Set的最后一个元素
说明:返回Set中小于e的最大元素
说明:返回Set中小于/等于e的最大元素
说明:返回Set中大于/等于e的最小元素
说明:返回Set中大于e的最小元素
说明:获取第一个元素,并将该元素从TreeMap中删除。
说明:获取最后一个元素,并将该元素从TreeMap中删除。
@Test
public void test1() {
NavigableSet set = new TreeSet<>();
set.add(5);
set.add(4);
set.add(5);
set.add(3);
set.add(1);
set.add(9);
//正顺序遍历
System.out.print("正序遍历:" );
set.forEach(item -> {
System.out.print(item + " ");
});
System.out.println();
//逆序遍历
System.out.print("逆序遍历:" );
set.descendingIterator().forEachRemaining(item -> {
System.out.print(item + " ");
});
}
复制代码
运行结果:
@Test
public void test2() {
// 自定义排序器
NavigableSet set = new TreeSet<>((o1, o2) -> o2 - o1);
set.add(5);
set.add(4);
set.add(5);
set.add(3);
set.add(1);
set.add(9);
//正顺序遍历
System.out.print("正序遍历:" );
set.forEach(item -> {
System.out.print(item + " ");
});
System.out.println();
}
复制代码
运行结果:
@Test
public void test3() {
NavigableSet set = new TreeSet<>();
set.add(null);
}
复制代码
运行结果:
@Test
public void test4() {
String val;
// 新建TreeSet
TreeSet tSet = new TreeSet();
// 将元素添加到TreeSet中
tSet.add("aaa");
// Set中不允许重复元素,所以只会保存一个“aaa”
tSet.add("aaa");
tSet.add("bbb");
tSet.add("eee");
tSet.add("ddd");
tSet.add("ccc");
System.out.println("TreeSet:" + tSet);
// 打印TreeSet的实际大小
System.out.printf("size : %d\n", tSet.size());
// 导航方法
// floor(小于、等于)
System.out.printf("floor bbb: %s\n", tSet.floor("bbb"));
// lower(小于)
System.out.printf("lower bbb: %s\n", tSet.lower("bbb"));
// ceiling(大于、等于)
System.out.printf("ceiling bbb: %s\n", tSet.ceiling("bbb"));
// higher(大于)
System.out.printf("higher bbb: %s\n", tSet.higher("bbb"));
// subSet()
System.out.printf("subSet(aaa, true, ccc, true): %s\n", tSet.subSet("aaa", true, "ccc", true));
System.out.printf("subSet(aaa, true, ccc, false): %s\n", tSet.subSet("aaa", true, "ccc", false));
System.out.printf("subSet(aaa, false, ccc, true): %s\n", tSet.subSet("aaa", false, "ccc", true));
System.out.printf("subSet(aaa, false, ccc, false): %s\n", tSet.subSet("aaa", false, "ccc", false));
// headSet()
System.out.printf("headSet(ccc, true): %s\n", tSet.headSet("ccc", true));
System.out.printf("headSet(ccc, false): %s\n", tSet.headSet("ccc", false));
// tailSet()
System.out.printf("tailSet(ccc, true): %s\n", tSet.tailSet("ccc", true));
System.out.printf("tailSet(ccc, false): %s\n", tSet.tailSet("ccc", false));
}
复制代码
运行结果:
TreeSet实际上是TreeMap实现的,底层用到的数据结果是红黑树。当我们构造TreeSet时;若使用不带参数的构造函数,则TreeSet的使用自然比较器;若用户需要使用自定义的比较器,则需要使用带比较器的参数。
与HashSet相比,TreeSet的性能稍低些。add、remove、search等操作时间复杂度为O(log n),按照存储顺序打印n个元素则耗时为O(n)。
如果我们想要按序保存条目,并且按照升序或者降序对集合进行访问和遍历,那么TreeSet就应该作为首选集合。升序方式的操作与视图性能要强于降序方式。