Java collections framework 的 TreeSet
类提供了树形数据结构的功能。
它实现了 NavigableSet
接口。
创建 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<>();
// Using the add() method
evenNumbers.add(2);
evenNumbers.add(4);
evenNumbers.add(6);
System.out.println("TreeSet: " + evenNumbers);
TreeSet<Integer> numbers = new TreeSet<>();
numbers.add(1);
// Using the addAll() method
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);
// Calling iterator() method
Iterator<Integer> iterate = numbers.iterator();
System.out.print("TreeSet using Iterator: ");
// Accessing elements
while(iterate.hasNext()) {
System.out.print(iterate.next());
System.out.print(", ");
}
}
}
输出
TreeSet: [2, 5, 6] TreeSet using Iterator: 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);
// Using the remove() method
boolean value1 = numbers.remove(5);
System.out.println("Is 5 removed? " + value1);
// Using the removeAll() method
boolean value2 = numbers.removeAll(numbers);
System.out.println("Are all elements removed? " + value2);
}
}
输出
TreeSet: [2, 5, 6] Is 5 removed? true Are all elements removed? 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);
// Using the first() method
int first = numbers.first();
System.out.println("First Number: " + first);
// Using the last() method
int last = numbers.last();
System.out.println("Last Number: " + last);
}
}
输出
TreeSet: [2, 5, 6] First Number: 2 Last Number: 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);
// Using higher()
System.out.println("Using higher: " + numbers.higher(4));
// Using lower()
System.out.println("Using lower: " + numbers.lower(4));
// Using ceiling()
System.out.println("Using ceiling: " + numbers.ceiling(4));
// Using floor()
System.out.println("Using floor: " + numbers.floor(3));
}
}
输出
TreeSet: [2, 4, 5, 6] Using higher: 5 Using lower: 2 Using ceiling: 4 Using 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);
// Using pollFirst()
System.out.println("Removed First Element: " + numbers.pollFirst());
// Using pollLast()
System.out.println("Removed Last Element: " + numbers.pollLast());
System.out.println("New TreeSet: " + numbers);
}
}
输出
TreeSet: [2, 4, 5, 6] Removed First Element: 2 Removed Last Element: 6 New 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);
// Using headSet() with default boolean value
System.out.println("Using headSet without boolean value: " + numbers.headSet(5));
// Using headSet() with specified boolean value
System.out.println("Using headSet with boolean value: " + numbers.headSet(5, true));
}
}
输出
TreeSet: [2, 4, 5, 6] Using headSet without boolean value: [2, 4] Using headSet with boolean value: [2, 4, 5]
tailSet(element, booleanValue)
tailSet()
方法返回树集中指定 element(作为参数传递)之后的所有元素,包括指定的 element。
booleanValue 参数是可选的。它的默认值为 true
。
如果将 false
作为 booleanValue 传递,则该方法返回指定 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);
// Using tailSet() with default boolean value
System.out.println("Using tailSet without boolean value: " + numbers.tailSet(4));
// Using tailSet() with specified boolean value
System.out.println("Using tailSet with boolean value: " + numbers.tailSet(4, false));
}
}
输出
TreeSet: [2, 4, 5, 6] Using tailSet without boolean value: [4, 5, 6] Using tailSet with boolean value: [5, 6]
subSet(e1, bv1, e2, bv2)
subSet()
方法返回 e1 和 e2 之间的所有元素,包括 e1。
bv1 和 bv2 是可选参数。 bv1 的默认值为 true
,bv2 的默认值为 false
。
如果将 false
作为 bv1 传递,则该方法返回 e1 和 e2 之间的所有元素,但不包括 e1
。
如果将 true
作为 bv2 传递,则该方法返回 e1 和 e2 之间的所有元素,包括 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);
// Using subSet() with default boolean value
System.out.println("Using subSet without boolean value: " + numbers.subSet(4, 6));
// Using subSet() with specified boolean value
System.out.println("Using subSet with boolean value: " + numbers.subSet(4, false, 6, true));
}
}
输出
TreeSet: [2, 4, 5, 6] Using subSet without boolean value: [4, 5] Using subSet with boolean value: [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);
// Union of two sets
numbers.addAll(evenNumbers);
System.out.println("Union is: " + numbers);
}
}
输出
TreeSet1: [2, 4] TreeSet2: [1, 2, 3] Union is: [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);
// Intersection of two sets
numbers.retainAll(evenNumbers);
System.out.println("Intersection is: " + numbers);
}
}
输出
TreeSet1: [2, 4] TreeSet2: [1, 2, 3] Intersection is: [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);
// Difference between two sets
numbers.removeAll(evenNumbers);
System.out.println("Difference is: " + numbers);
}
}
输出
TreeSet1: [2, 4] TreeSet2: [1, 2, 3, 4] Difference is: [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);
// Check if primeNumbers is subset of numbers
boolean result = numbers.containsAll(primeNumbers);
System.out.println("Is TreeSet2 subset of TreeSet1? " + result);
}
}
输出
TreeSet1: [1, 2, 3, 4] TreeSet2: [2, 3] Is TreeSet2 subset of TreeSet1? True
TreeSet 的其他方法
方法 | 描述 |
---|---|
clone() |
创建 TreeSet 的副本 |
contains() |
搜索 TreeSet 中指定的元素并返回布尔结果 |
isEmpty() |
检查 TreeSet 是否为空 |
size() |
返回 TreeSet 的大小 |
clear() |
从 TreeSet 中移除所有元素 |
要了解更多信息,请访问 Java TreeSet (官方 Java 文档)。
TreeSet 与 HashSet
TreeSet
和 HashSet
都实现了 Set
接口。但是,它们之间存在一些差异。
- 与
HashSet
不同,TreeSet
中的元素是按某种顺序存储的。这是因为TreeSet
也实现了SortedSet
接口。 TreeSet
提供了一些方便导航的方法。例如,first()
、last()
、headSet()
、tailSet()
等。这是因为TreeSet
还实现了NavigableSet
接口。- 对于 add、remove、contains 和 size 等基本操作,
HashSet
比TreeSet
更快。
TreeSet Comparator
在以上所有示例中,树集元素均按自然顺序排序。但是,我们也可以自定义元素的排序。
为此,我们需要创建自己的比较器类,树集中的元素将根据该类进行排序。例如,
import java.util.TreeSet;
import java.util.Comparator;
class Main {
public static void main(String[] args) {
// Creating a tree set with a customized comparator
TreeSet<String> animals = new TreeSet<>(new CustomComparator());
animals.add("Dog");
animals.add("Zebra");
animals.add("Cat");
animals.add("Horse");
System.out.println("TreeSet: " + animals);
}
// Creating a comparator class
public static class CustomComparator implements Comparator<String> {
@Override
public int compare(String animal1, String animal2) {
int value = animal1.compareTo(animal2);
// elements are sorted in reverse order
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 文档)。