Java TreeSet 类

2025年4月1日 | 阅读10分钟
Java TreeSet Class

Java TreeSet 类实现了Set接口,它使用一棵树进行存储。它继承了AbstractSet类并实现了NavigableSet接口。TreeSet类的对象按升序存储。

Java TreeSet 类的重要注意事项如下:

  • Java TreeSet 类只包含唯一元素,类似于HashSet。
  • Java TreeSet 类的访问和检索时间非常快。
  • Java TreeSet 类不允许空元素。
  • Java TreeSet 类不是同步的。
  • Java TreeSet 类保持升序。
  • Java TreeSet 类只包含唯一元素,类似于HashSet。
  • Java TreeSet 类的访问和检索时间非常快。
  • Java TreeSet 类不允许空元素。
  • Java TreeSet 类不是同步的。
  • Java TreeSet 类保持升序。
  • TreeSet 只能允许实现Comparable接口的泛型类型。例如,StringBuffer类实现了Comparable接口。

TreeSet 类的内部工作原理

TreeSet 是使用二叉搜索树实现的,该树是自平衡的,就像红黑树一样。因此,搜索、删除和添加等操作需要O(log(N))的时间。这是因为有自平衡树。它的目的是确保对于所有提到的操作,树的高度都不会超过 O(log(N))。因此,它是用于存储大量已排序数据并对其进行操作的有效数据结构之一。

TreeSet 功能的关键方面

  • 红黑树结构:树中的每个节点都被分配了一个颜色(红色或黑色),这在保持树的平衡方面起着至关重要的作用。这种策略性的着色有助于防止树变得倾斜,从而提高性能,并确保操作快速高效地处理。
  • 动态重新平衡:每当添加或删除元素时,TreeSet 都会动态调整其内部结构。它确保集合中的元素始终按升序排列,这对于需要有序数据的应用程序来说是高度可靠的。
  • 处理重复项:TreeSet 被设计为只存储唯一元素。集合会优雅地处理添加重复项的尝试,确保只保留不同的元素。这对于数据完整性至关重要,并简化了对唯一性至关重要的集合的管理。
  • 顺序确定:TreeSet 中元素的排序可以遵循元素的自然顺序,也可以由自定义比较器定义。这种灵活性允许开发人员控制元素在集合中的比较和排序方式。

TreeSet 类的同步

如上所述,TreeSet 类不是同步的。这意味着,如果有多个线程并发访问一个 Tree set,并且其中一个访问线程修改了它,则必须手动进行同步。这通常是通过执行一些封装集合的对象同步技术来完成的。然而,在找不到这样的对象的情况下,必须使用Collections.synchronizedSet()方法来包装该集合。建议在创建时使用该方法,以避免对集合进行不同步访问。下面的代码片段展示了这一点。

TreeSet 类的同步

如上所述,TreeSet 类不是同步的。这意味着如果多个线程并发访问一个 Tree set,并且其中一个访问线程修改了它,则必须手动进行同步。这通常是通过执行一些封装集合的对象同步来完成的。然而,在找不到这样的对象的情况下,必须使用Collections.synchronizedSet()方法来包装该集合。建议在创建时使用该方法,以避免对集合进行不同步访问。下面的代码片段展示了这一点。

TreeSet 类的继承层次结构

如上图所示,Java TreeSet 类实现了NavigableSet接口。NavigableSet接口按继承顺序扩展了SortedSet、Set、Collection和Iterable接口。

Java 中的 TreeSet 类是 Java 集合框架的关键部分,它旨在以排序且唯一的方式存储元素,确保没有重复项。以下是其层次结构的关键点:

SortedSet 接口:TreeSet 直接实现 SortedSet 接口,该接口扩展了基本的 Set 接口。此接口引入了用于维护元素之间顺序的操作方法,并支持范围视图功能,这对于有序数据操作至关重要。

NavigableSet 接口:位于 SortedSet 的下方,NavigableSet 接口增加了高级导航功能。它允许 TreeSet 根据元素相对于集合中其他元素的精确关系来检索元素,从而增强了其高效数据查询和操作的功能。

效率:TreeSet 由使用红黑树结构的 TreeMap 支持,可以以对数时间复杂度执行添加、删除和包含等基本操作,使其成为需要快速数据处理的高性能应用程序的理想选择。

TreeSet 类声明

让我们看看 java.util.TreeSet 类的声明。

声明的组成部分

  1. TreeSet<E> 类:TreeSet 类声明为 public,这意味着它可以从任何包中的任何类访问。
    <E> 表示 TreeSet 是一个泛型类,能够存储用户指定的任何类型的对象。
  2. AbstractSet<E>:TreeSet 类扩展了 AbstractSet 接口,该接口提供了 Set 接口的骨架实现。这意味着 TreeSet 类继承了 AbstractSet 接口的所有抽象方法。
  3. NavigableSet<E>:通过实现 NavigableSet,TreeSet 获得了用于导航集合相对于给定目标元素的方法,例如 higher、lower、ceiling 和 floor。该接口扩展了 SortedSet,而 SortedSet 又扩展了 Set,确保 TreeSet 拥有排序和可导航集合的所有功能。
  4. Cloneable:这表示 TreeSet 支持克隆,允许安全地复制它而不影响原始集合。
  5. Serializable:它确保 TreeSet 可以被序列化,这意味着它的状态可以转换为字节流,然后可以恢复为 TreeSet 的副本。序列化对于保存对象的状态以供以后检索或传输到不同的处理环境至关重要。

Java TreeSet 类构造函数

构造函数描述
TreeSet()用于构建一个空的 tree set,它将根据 tree set 的自然顺序按升序排序。
TreeSet(Collection<? extends E> c)用于构建一个新的 tree set,其中包含集合 c 的元素。
TreeSet(Comparator<? super E> comparator)用于构建一个空的 tree set,它将根据给定的比较器排序。
TreeSet(SortedSet<E> s)用于构建一个 TreeSet,其中包含给定 SortedSet 的元素。

Java TreeSet 类的方法

方法描述
boolean add(E e)如果指定的元素尚不存在,则将其添加到此集合中。
boolean addAll(Collection<? extends E> c)将指定集合中的所有元素添加到此集合中。
E ceiling(E e)返回集合中小于或等于指定元素的相等或最接近的较大元素,如果不存在这样的元素,则返回 null。
Comparator<? super E> comparator()返回一个排列元素的比较器。
IteratordescendingIterator()用于按降序遍历元素。
NavigableSetdescendingSet()返回反向排序的元素。
E floor(E e)返回集合中小于或等于指定元素的相等或最接近的较小元素,如果不存在这样的元素,则返回 null。
SortedSetheadSet(E toElement)返回小于指定元素的元素组。
NavigableSetheadSet(E toElement, boolean inclusive)返回小于或等于(如果 inclusive 为 true)指定元素的元素组。
E higher(E e)返回集合中小于指定元素的、相等或最接近的较大元素,如果不存在这样的元素,则返回 null。
Iteratoriterator()用于按升序遍历元素。
E lower(E e)返回集合中小于指定元素的、相等或最接近的较小元素,如果不存在这样的元素,则返回 null。
E pollFirst()检索并删除最低(第一个)元素。
E pollLast()检索并删除最高(最后一个)元素。
Spliteratorspliterator()用于在元素上创建延迟绑定且快速失败的迭代器。
NavigableSetsubSet(E fromElement, boolean fromInclusive, E toElement, boolean toInclusive)返回介于给定范围内的元素集合。
SortedSetsubSet(E fromElement, E toElement))返回介于给定范围内的元素集合,该范围包括 fromElement 并排除 toElement。
SortedSettailSet(E fromElement)返回大于或等于指定元素的元素集合。
NavigableSettailSet(E fromElement, boolean inclusive)返回大于或等于(如果 inclusive 为 true)指定元素的元素集合。
boolean contains(Object o)如果此集合包含指定元素,则返回 true。
boolean isEmpty()如果此集合不包含任何元素,则返回 true。
boolean remove(Object o)如果指定的元素在此集合中,则将其从此集合中移除。
void clear()从此集合中移除所有元素。
Object clone()返回此 TreeSet 实例的浅拷贝。
E first()返回当前在此排序集合中的第一个(最低)元素。
E last()返回当前在此排序集合中的最后一个(最高)元素。
int size()返回此集合中的元素数量。

Java TreeSet 示例

Java TreeSet 示例 1

让我们看一个简单的 Java TreeSet 示例。

文件名:TreeSet1.java

输出

Ajay
Ravi
Vijay

Java TreeSet 示例 2

让我们看一个按降序遍历元素的示例。

文件名:TreeSet2.java

输出

Traversing element through Iterator in descending order
Vijay
Ravi
Ajay
Traversing element through NavigableSet in descending order
Vijay
Ravi
Ajay

Java TreeSet 示例 3

让我们看一个检索和删除最高和最低值的示例。

文件名:TreeSet3.java

输出

Lowest Value: 12
Highest Value: 66

Java TreeSet 示例 4

在此示例中,我们将执行各种 NavigableSet 操作。

文件名:TreeSet4.java

输出

Initial Set: [A, B, C, D, E]
Reverse Set: [E, D, C, B, A]
Head Set: [A, B, C]
SubSet: [B, C, D, E]
TailSet: [D, E]

Java TreeSet 示例 5

在此示例中,我们将执行各种 SortedSetSet 操作。

文件名:TreeSet5.java

输出

Intial Set: [A, B, C, D, E]
Head Set: [A, B]
SubSet: [A, B, C, D]
TailSet: [C, D, E]

Java TreeSet 示例:图书

让我们看一个 TreeSet 示例,其中我们向集合中添加书籍并打印所有书籍。TreeSet 中的元素必须是 Comparable 类型。String 和包装类默认是 Comparable 的。要在 TreeSet 中添加用户定义的对象,您需要实现 Comparable 接口。

文件名:TreeSetExample.java

输出

101 Data Communications & Networking Forouzan Mc Graw Hill 4
121 Let us C Yashwant Kanetkar BPB 8
233 Operating System Galvin Wiley 6

TreeSet 中的 ClassCast Exception

如果我们添加了一个未实现 Comparable 接口的类的对象,则会引发 ClassCast Exception。请看以下程序。

文件名:ClassCastExceptionTreeSet.java

输出

Exception in thread "main" java.lang.ClassCastException: class Employee cannot be cast to class java.lang.Comparable (Employee is in unnamed module of loader 'app'; java.lang.Comparable is in module java.base of loader 'bootstrap')
	at java.base/java.util.TreeMap.compare(TreeMap.java:1569)
	at java.base/java.util.TreeMap.addEntryToEmptyMap(TreeMap.java:776)
	at java.base/java.util.TreeMap.put(TreeMap.java:785)
	at java.base/java.util.TreeMap.put(TreeMap.java:534)
	at java.base/java.util.TreeSet.add(TreeSet.java:255)
	at ClassCastExceptionTreeSet.main(ClassCastExceptionTreeSet.java:52)

解释:在上面的程序中,需要实现 Comparable 接口。这是因为 TreeSet 维护排序顺序,并且为了进行排序,必须比较插入 TreeSet 的不同对象,这可以通过实现 Comparable 接口来实现。

TreeSet 与 HashSet

特性TreeSetHashSet
底层数据结构红黑树哈希表
元素顺序保持元素排序,便于有序遍历和快速范围搜索。不维护任何顺序;元素的排列由哈希函数决定。
基本操作的性能时间复杂度略有增加;add、delete 和 contain 等操作的时间复杂度为 O(logN)。基本操作(如 add、delete 和 contain)的时间复杂度为 O(1)(常数时间),使其非常高效。
最佳用例更适用于需要有序数据管理的应用,例如范围查询或顺序访问。最适合需要快速检索和操作但元素顺序不重要的场景。
排序根据元素的自然顺序或指定的比较器自动对元素进行排序。不对元素进行排序;存储是基于哈希的。
应用适用性更适用于需要将元素保持为排序状态的应用。更适合需要快速访问且不关心元素顺序的应用。

下一个主题Java PriorityQueue 类