跳到主要内容

Java TreeSet 类

提示
  1. TreeSet 的基本功能:提供树形数据结构,继承自 NavigableSet 接口,允许自然顺序或自定义比较器对元素排序。
  2. 插入和访问元素:使用 add()addAll() 方法插入元素,通过 iterator() 方法和各种导航方法(如 first()last())访问元素。
  3. 集合操作和比较器:支持集合的并集、交集、差集操作(使用 addAll()retainAll()removeAll() 方法),可通过实现 Comparator 接口自定义排序规则。

Java 集合框架中的 TreeSet 类提供了树形数据结构的功能。

它扩展了 NavigableSet 接口

Java TreeSet 类实现了 NavigableSet 接口。

创建 TreeSet

要创建树集(TreeSet),首先我们必须导入 java.util.TreeSet 包。

导入包后,这里是如何在 Java 中创建 TreeSet 的方法。

TreeSet<Integer> numbers = new TreeSet<>();

这里,我们创建了一个不带任何参数的 TreeSet。在这种情况下,TreeSet 中的元素会按自然顺序(升序)排序。

不过,我们可以使用 Comparator 接口来自定义元素的排序方式。我们将在本教程后面了解它。

TreeSet 的方法

TreeSet 类提供了多种方法,允许我们对集合执行各种操作。

向 TreeSet 插入元素

  • add() - 将指定元素插入到集合中
  • addAll() - 将指定集合的所有元素插入到集合中

例如,

import java.util.TreeSet;

class Main {
public static void main(String[] args) {

TreeSet<Integer> evenNumbers = new TreeSet<>();

// 使用 add() 方法
evenNumbers.add(2);
evenNumbers.add(4);
evenNumbers.add(6);
System.out.println("TreeSet: " + evenNumbers);

TreeSet<Integer> numbers = new TreeSet<>();
numbers.add(1);

// 使用 addAll() 方法
numbers.addAll(evenNumbers);
System.out.println("New TreeSet: " + numbers);
}
}

输出

TreeSet: [2, 4, 6]
New TreeSet: [1, 2, 4, 6]

访问 TreeSet 元素

要访问树集的元素,我们可以使用 iterator() 方法。要使用此方法,我们必须导入 java.util.Iterator 包。例如,

import java.util.TreeSet;
import java.util.Iterator;

class Main {
public static void main(String[] args) {
TreeSet<Integer> numbers = new TreeSet<>();
numbers.add(2);
numbers.add(5);
numbers.add(6);
System.out.println("TreeSet: " + numbers);

// 调用 iterator() 方法
Iterator<Integer> iterate = numbers.iterator();
System.out.print("使用 Iterator 的 TreeSet: ");
// 访问元素
while(iterate.hasNext()) {
System.out.print(iterate.next());
System.out.print(", ");
}
}
}

输出

TreeSet: [2, 5, 6]
使用 IteratorTreeSet: 2, 5, 6,

删除元素

  • remove() - 从集合中移除指定元素
  • removeAll() - 从集合中移除所有元素

例如,

import java.util.TreeSet;

class Main {
public static void main(String[] args) {
TreeSet<Integer> numbers = new TreeSet<>();
numbers.add(2);
numbers.add(5);
numbers.add(6);
System.out.println("TreeSet: " + numbers);

// 使用 remove() 方法
boolean value1 = numbers.remove(5);
System.out.println("5 被移除了吗? " + value1);

// 使用 removeAll() 方法
boolean value2 = numbers.removeAll(numbers);
System.out.println("所有元素都被移除了吗? " + value2);
}
}

输出

TreeSet: [2, 5, 6]
5 被移除了吗? true
所有元素都被移除了吗? true

导航方法

由于 TreeSet 类实现了 NavigableSet,它提供了多种方法来遍历树集的元素。

1. first() 和 last() 方法

  • first() - 返回集合的第一个元素
  • last() - 返回集合的最后一个元素

例如,

import java.util.TreeSet;

class Main {
public static void main(String[] args) {
TreeSet<Integer> numbers = new TreeSet<>();
numbers.add(2);
numbers.add(5);
numbers.add(6);
System.out.println("TreeSet: " + numbers);

// 使用 first() 方法
int first = numbers.first();
System.out.println("第一个数字: " + first);

// 使用 last() 方法
int last = numbers.last();
System.out.println("最后一个数字: " + last);
}
}

输出

TreeSet: [2, 5, 6]
第一个数字: 2
最后一个数字: 6

2. ceiling(), floor(), higher() 和 lower() 方法

  • higher(element) - 返回所有大于指定 element 的元素中的最小元素。
  • lower(element) - 返回所有小于指定 element 的元素中的最大元素。
  • ceiling(element) - 返回所有大于指定 element 的元素中的最小元素。如果树集中存在传入的 element,则返回作为参数传入的 element
  • floor(element) - 返回所有小于指定 element 的元素中的最大元素。如果树集中存在传入的 element,则返回作为参数传入的 element

例如,

import java.util.TreeSet;

class Main {
public static void main(String[] args) {
TreeSet<Integer> numbers = new TreeSet<>();
numbers.add(2);
numbers.add(5);
numbers.add(4);
numbers.add(6);
System.out.println("TreeSet: " + numbers);

// 使用 higher()
System.out.println("使用 higher: " + numbers.higher(4));

// 使用 lower()
System.out.println("使用 lower: " + numbers.lower(4));

// 使用 ceiling()
System.out.println("使用 ceiling: " + numbers.ceiling(4));

// 使用 floor()
System.out.println("使用 floor: " + numbers.floor(3));

}
}
```**输出**

```java
TreeSet: [2, 4, 5, 6]
使用 higher: 5
使用 lower: 2
使用 ceiling: 4
使用 floor: 2

3. pollFirst() 和 pollLast() 方法

  • pollFirst() - 返回并移除集合中的第一个元素
  • pollLast() - 返回并移除集合中的最后一个元素

例如,

import java.util.TreeSet;

class Main {
public static void main(String[] args) {
TreeSet<Integer> numbers = new TreeSet<>();
numbers.add(2);
numbers.add(5);
numbers.add(4);
numbers.add(6);
System.out.println("TreeSet: " + numbers);

// 使用 pollFirst()
System.out.println("移除的第一个元素: " + numbers.pollFirst());

// 使用 pollLast()
System.out.println("移除的最后一个元素: " + numbers.pollLast());

System.out.println("新的 TreeSet: " + numbers);
}
}

输出

TreeSet: [2, 4, 5, 6]
移除的第一个元素: 2
移除的最后一个元素: 6
新的 TreeSet: [4, 5]

4. headSet(), tailSet() 和 subSet() 方法

headSet(element, booleanValue)

headSet() 方法返回在指定 element(作为参数传入)之前的所有树集元素。

booleanValue 参数是可选的。其默认值为 false

如果传入 true 作为 booleanValue,该方法返回在指定元素之前包括该指定元素的所有元素。

例如,

import java.util.TreeSet;

class Main {
public static void main(String[] args) {
TreeSet<Integer> numbers = new TreeSet<>();
numbers.add(2);
numbers.add(5);
numbers.add(4);
numbers.add(6);
System.out.println("TreeSet: " + numbers);

// 使用默认布尔值的 headSet()
System.out.println("未使用布尔值的 headSet: " + numbers.headSet(5));

// 使用指定布尔值的 headSet()
System.out.println("使用布尔值的 headSet: " + numbers.headSet(5, true));
}
}

输出

TreeSet: [2, 4, 5, 6]
未使用布尔值的 headSet: [2, 4]
使用布尔值的 headSet: [2, 4, 5]

tailSet(element, booleanValue)

tailSet() 方法返回在指定 element(作为参数传入)之后的所有树集元素,包括该指定元素。

booleanValue 参数是可选的。其默认值为 true

如果传入 false 作为 booleanValue,该方法返回在指定元素之后但不包括该指定元素的所有元素。

例如,

import java.util.TreeSet;

class Main {
public static void main(String[] args) {
TreeSet<Integer> numbers = new TreeSet<>();
numbers.add(2);
numbers.add(5);
numbers.add(4);
numbers.add(6);
System.out.println("TreeSet: " + numbers);

// 使用默认布尔值的 tailSet()
System.out.println("未使用布尔值的 tailSet: " + numbers.tailSet(4));

// 使用指定布尔值的 tailSet()
System.out.println("使用布尔值的 tailSet: " + numbers.tailSet(4, false));
}
}
```**输出**

```java
TreeSet: [2, 4, 5, 6]
未使用布尔值的 tailSet: [4, 5, 6]
使用布尔值的 tailSet: [5, 6]

subSet(e1, bv1, e2, bv2)

subSet() 方法返回 e1e2 之间的所有元素,包括 e1

bv1bv2 是可选参数。bv1 的默认值是 truebv2 的默认值是 false

如果为 bv1 传入 false,该方法返回 e1e2 之间的所有元素,但不包括 e1

如果为 bv2 传入 true,该方法返回 e1e2 之间的所有元素,包括 e1

例如,

import java.util.TreeSet;

class Main {
public static void main(String[] args) {
TreeSet<Integer> numbers = new TreeSet<>();
numbers.add(2);
numbers.add(5);
numbers.add(4);
numbers.add(6);
System.out.println("TreeSet: " + numbers);

// 使用默认布尔值的 subSet()
System.out.println("未使用布尔值的 subSet: " + numbers.subSet(4, 6));

// 使用指定布尔值的 subSet()
System.out.println("使用布尔值的 subSet: " + numbers.subSet(4, false, 6, true));
}
}

输出

TreeSet: [2, 4, 5, 6]
未使用布尔值的 subSet: [4, 5]
使用布尔值的 subSet: [5, 6]

集合操作

TreeSet 类的方法还可以用来执行各种集合操作。

集合的并集

要执行两个集合的并集,我们使用 addAll() 方法。例如,

import java.util.TreeSet;;

class Main {
public static void main(String[] args) {
TreeSet<Integer> evenNumbers = new TreeSet<>();
evenNumbers.add(2);
evenNumbers.add(4);
System.out.println("TreeSet1: " + evenNumbers);

TreeSet<Integer> numbers = new TreeSet<>();
numbers.add(1);
numbers.add(2);
numbers.add(3);
System.out.println("TreeSet2: " + numbers);

// 两个集合的并集
numbers.addAll(evenNumbers);
System.out.println("并集是: " + numbers);
}
}

输出

TreeSet1: [2, 4]
TreeSet2: [1, 2, 3]
并集是: [1, 2, 3, 4]

集合的交集

要执行两个集合的交集,我们使用 retainAll() 方法。例如,

import java.util.TreeSet;;

class Main {
public static void main(String[] args) {
TreeSet<Integer> evenNumbers = new TreeSet<>();
evenNumbers.add(2);
evenNumbers.add(4);
System.out.println("TreeSet1: " + evenNumbers);

TreeSet<Integer> numbers = new TreeSet<>();
numbers.add(1);
numbers.add(2);
numbers.add(3);
System.out.println("TreeSet2: " + numbers);

// 两个集合的交集
numbers.retainAll(evenNumbers);
System.out.println("交集是: " + numbers);
}
}
```**输出**

```java
TreeSet1: [2, 4]
TreeSet2: [1, 2, 3]
交集是: [2]

集合的差集

要计算两个集合之间的差集,我们可以使用 removeAll() 方法。例如,

import java.util.TreeSet;;

class Main {
public static void main(String[] args) {
TreeSet<Integer> evenNumbers = new TreeSet<>();
evenNumbers.add(2);
evenNumbers.add(4);
System.out.println("TreeSet1: " + evenNumbers);

TreeSet<Integer> numbers = new TreeSet<>();
numbers.add(1);
numbers.add(2);
numbers.add(3);
numbers.add(4);
System.out.println("TreeSet2: " + numbers);

// 两个集合的差集
numbers.removeAll(evenNumbers);
System.out.println("差集是: " + numbers);
}
}

输出

TreeSet1: [2, 4]
TreeSet2: [1, 2, 3, 4]
差集是: [1, 3]

集合的子集

要检查一个集合是否是另一个集合的子集,我们使用 containsAll() 方法。例如,

import java.util.TreeSet;

class Main {
public static void main(String[] args) {
TreeSet<Integer> numbers = new TreeSet<>();
numbers.add(1);
numbers.add(2);
numbers.add(3);
numbers.add(4);
System.out.println("TreeSet1: " + numbers);

TreeSet<Integer> primeNumbers = new TreeSet<>();
primeNumbers.add(2);
primeNumbers.add(3);
System.out.println("TreeSet2: " + primeNumbers);

// 检查 primeNumbers 是否是 numbers 的子集
boolean result = numbers.containsAll(primeNumbers);
System.out.println("TreeSet2 是 TreeSet1 的子集吗? " + result);
}
}

输出

TreeSet1: [1, 2, 3, 4]
TreeSet2: [2, 3]
TreeSet2TreeSet1 的子集吗? True

TreeSet 的其他方法

方法描述
clone()创建 TreeSet 的副本
contains()搜索 TreeSet 中的指定元素并返回布尔结果
isEmpty()检查 TreeSet 是否为空
size()返回 TreeSet 的大小
clear()TreeSet 中移除所有元素

要了解更多,请访问 Java TreeSet (官方 Java 文档)

TreeSet 与 HashSet 的比较

TreeSetHashSet 都实现了 Set 接口。然而,它们之间存在一些差异。

  • HashSet 不同,TreeSet 中的元素是有序存储的。这是因为 TreeSet 也实现了 SortedSet 接口。
  • TreeSet 提供了一些便于导航的方法。例如,first()last()headSet()tailSet() 等。这是因为 TreeSet 还实现了 NavigableSet 接口。
  • HashSet 在添加、删除、检查是否包含元素和获取大小等基本操作上比 TreeSet 更快。

TreeSet 的比较器

在上述所有示例中,树集(TreeSet)元素都是自然排序的。然而,我们也可以自定义元素的排序方式。

为此,我们需要创建自己的比较器类(comparator class),基于此类对树集中的元素进行排序。例如,

import java.util.TreeSet;
import java.util.Comparator;

class Main {
public static void main(String[] args) {

// 创建一个带有自定义比较器的树集
TreeSet<String> animals = new TreeSet<>(new CustomComparator());

animals.add("Dog");
animals.add("Zebra");
animals.add("Cat");
animals.add("Horse");
System.out.println("TreeSet: " + animals);
}

// 创建比较器类
public static class CustomComparator implements Comparator<String> {

@Override
public int compare(String animal1, String animal2) {
int value = animal1.compareTo(animal2);

// 元素按照逆序排序
if (value > 0) {
return -1;
}
else if (value < 0) {
return 1;
}
else {
return 0;
}
}
}
}

输出

TreeSet: [Zebra, Horse, Dog, Cat]

在上面的示例中,我们创建了一个树集,并将 CustomComparator 类作为参数传入。

CustomComparator 类实现了 Comparator 接口。

然后我们重写了 compare() 方法。现在这个方法将以逆序对元素进行排序。

要了解更多,请访问 Java Comparator (官方 Java 文档)