原文: https://www.programiz.com/java-programming/treeset

在本教程中,我们将借助示例学习 Java TreeSet类及其各种操作和方法。

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

它扩展了NavigableSet接口

Java `TreeSet` - 图1


创建一个TreeSet

为了创建树集,我们必须首先导入java.util.TreeSet包。

导入包后,可以使用以下方法在 Java 中创建TreeSet

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

在这里,我们创建了没有任何参数的TreeSet。 在这种情况下,TreeSet中的元素会自然排序(升序)。

但是,我们可以使用Comparator接口自定义元素的排序。 我们将在本教程的后面部分中学习它。


TreeSet的方法

TreeSet类提供了各种方法,使我们可以对设备执行各种操作。


将元素插入TreeSet

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

例如,

  1. import java.util.TreeSet;
  2. class Main {
  3. public static void main(String[] args) {
  4. TreeSet<Integer> evenNumbers = new TreeSet<>();
  5. // Using the add() method
  6. evenNumbers.add(2);
  7. evenNumbers.add(4);
  8. evenNumbers.add(6);
  9. System.out.println("TreeSet: " + evenNumbers);
  10. TreeSet<Integer> numbers = new TreeSet<>();
  11. numbers.add(1);
  12. // Using the addAll() method
  13. numbers.addAll(evenNumbers);
  14. System.out.println("New TreeSet: " + numbers);
  15. }
  16. }

输出

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

访问TreeSet元素

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

  1. import java.util.TreeSet;
  2. import java.util.Iterator;
  3. class Main {
  4. public static void main(String[] args) {
  5. TreeSet<Integer> numbers = new TreeSet<>();
  6. numbers.add(2);
  7. numbers.add(5);
  8. numbers.add(6);
  9. System.out.println("TreeSet: " + numbers);
  10. // Calling iterator() method
  11. Iterator<Integer> iterate = numbers.iterator();
  12. System.out.print("TreeSet using Iterator: ");
  13. // Accessing elements
  14. while(iterate.hasNext()) {
  15. System.out.print(iterate.next());
  16. System.out.print(", ");
  17. }
  18. }
  19. }

输出

  1. TreeSet: [2, 5, 6]
  2. TreeSet using Iterator: 2, 5, 6,

删除元素

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

例如:

  1. import java.util.TreeSet;
  2. class Main {
  3. public static void main(String[] args) {
  4. TreeSet<Integer> numbers = new TreeSet<>();
  5. numbers.add(2);
  6. numbers.add(5);
  7. numbers.add(6);
  8. System.out.println("TreeSet: " + numbers);
  9. // Using the remove() method
  10. boolean value1 = numbers.remove(5);
  11. System.out.println("Is 5 removed? " + value1);
  12. // Using the removeAll() method
  13. boolean value2 = numbers.removeAll(numbers);
  14. System.out.println("Are all elements removed? " + value2);
  15. }
  16. }

输出

  1. TreeSet: [2, 5, 6]
  2. Is 5 removed? true
  3. Are all elements removed? true

用于导航的方法

由于TreeSet类实现了NavigableSet,因此它提供了各种方法来浏览树集的元素。

1. first()last()方法

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

例如:

  1. import java.util.TreeSet;
  2. class Main {
  3. public static void main(String[] args) {
  4. TreeSet<Integer> numbers = new TreeSet<>();
  5. numbers.add(2);
  6. numbers.add(5);
  7. numbers.add(6);
  8. System.out.println("TreeSet: " + numbers);
  9. // Using the first() method
  10. int first = numbers.first();
  11. System.out.println("First Number: " + first);
  12. // Using the last() method
  13. int last = numbers.last();
  14. System.out.println("Last Number: " + last);
  15. }
  16. }

输出

  1. TreeSet: [2, 5, 6]
  2. First Number: 2
  3. Last Number: 6

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

  • upper(element) - 返回大于指定element的那些元素中的最低元素。
  • lower(element) - 返回小于指定element的那些元素中最大的元素。
  • ceiling(element) - 返回大于指定element的那些元素中的最低元素。 如果通过的element存在于树集中,则它返回作为参数传递的element
  • floor(element) - 返回小于指定element的那些元素中最大的元素。 如果传递的element存在于树集中,则它返回作为参数传递的element

例如:

  1. import java.util.TreeSet;
  2. class Main {
  3. public static void main(String[] args) {
  4. TreeSet<Integer> numbers = new TreeSet<>();
  5. numbers.add(2);
  6. numbers.add(5);
  7. numbers.add(4);
  8. numbers.add(6);
  9. System.out.println("TreeSet: " + numbers);
  10. // Using higher()
  11. System.out.println("Using higher: " + numbers.higher(4));
  12. // Using lower()
  13. System.out.println("Using lower: " + numbers.lower(4));
  14. // Using ceiling()
  15. System.out.println("Using ceiling: " + numbers.ceiling(4));
  16. // Using floor()
  17. System.out.println("Using floor: " + numbers.floor(3));
  18. }
  19. }

输出

  1. TreeSet: [2, 4, 5, 6]
  2. Using higher: 5
  3. Using lower: 2
  4. Using ceiling: 4
  5. Using floor: 2

3. pollfirst()pollLast()方法

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

例如:

  1. import java.util.TreeSet;
  2. class Main {
  3. public static void main(String[] args) {
  4. TreeSet<Integer> numbers = new TreeSet<>();
  5. numbers.add(2);
  6. numbers.add(5);
  7. numbers.add(4);
  8. numbers.add(6);
  9. System.out.println("TreeSet: " + numbers);
  10. // Using pollFirst()
  11. System.out.println("Removed First Element: " + numbers.pollFirst());
  12. // Using pollLast()
  13. System.out.println("Removed Last Element: " + numbers.pollLast());
  14. System.out.println("New TreeSet: " + numbers);
  15. }
  16. }

输出

  1. TreeSet: [2, 4, 5, 6]
  2. Removed First Element: 2
  3. Removed Last Element: 6
  4. New TreeSet: [4, 5]

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


headSet(element, booleanValue)

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

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

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

例如:

  1. import java.util.TreeSet;
  2. class Main {
  3. public static void main(String[] args) {
  4. TreeSet<Integer> numbers = new TreeSet<>();
  5. numbers.add(2);
  6. numbers.add(5);
  7. numbers.add(4);
  8. numbers.add(6);
  9. System.out.println("TreeSet: " + numbers);
  10. // Using headSet() with default boolean value
  11. System.out.println("Using headSet without boolean value: " + numbers.headSet(5));
  12. // Using headSet() with specified boolean value
  13. System.out.println("Using headSet with boolean value: " + numbers.headSet(5, true));
  14. }
  15. }

输出

  1. TreeSet: [2, 4, 5, 6]
  2. Using headSet without boolean value: [2, 4]
  3. Using headSet with boolean value: [2, 4, 5]

tailSet(element, booleanValue)

tailSet()方法返回包含指定的element的指定element(作为参数传递)之后的树集的所有元素。

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

如果false作为booleanValue传递,则该方法返回指定的element之后的所有元素,而不包括指定的element

例如:

  1. import java.util.TreeSet;
  2. class Main {
  3. public static void main(String[] args) {
  4. TreeSet<Integer> numbers = new TreeSet<>();
  5. numbers.add(2);
  6. numbers.add(5);
  7. numbers.add(4);
  8. numbers.add(6);
  9. System.out.println("TreeSet: " + numbers);
  10. // Using tailSet() with default boolean value
  11. System.out.println("Using tailSet without boolean value: " + numbers.tailSet(4));
  12. // Using tailSet() with specified boolean value
  13. System.out.println("Using tailSet with boolean value: " + numbers.tailSet(4, false));
  14. }
  15. }

输出

  1. TreeSet: [2, 4, 5, 6]
  2. Using tailSet without boolean value: [4, 5, 6]
  3. Using tailSet with boolean value: [5, 6]

subSet(e1, bv1, e2, bv2)

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

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

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

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

例如:

  1. import java.util.TreeSet;
  2. class Main {
  3. public static void main(String[] args) {
  4. TreeSet<Integer> numbers = new TreeSet<>();
  5. numbers.add(2);
  6. numbers.add(5);
  7. numbers.add(4);
  8. numbers.add(6);
  9. System.out.println("TreeSet: " + numbers);
  10. // Using subSet() with default boolean value
  11. System.out.println("Using subSet without boolean value: " + numbers.subSet(4, 6));
  12. // Using subSet() with specified boolean value
  13. System.out.println("Using subSet with boolean value: " + numbers.subSet(4, false, 6, true));
  14. }
  15. }

输出

  1. TreeSet: [2, 4, 5, 6]
  2. Using subSet without boolean value: [4, 5]
  3. Using subSet with boolean value: [5, 6]

集的操作

TreeSet类的方法也可以用于执行各种设置操作。


并集

为了执行两个集合之间的联合,我们使用addAll()方法。 例如,

  1. import java.util.TreeSet;;
  2. class Main {
  3. public static void main(String[] args) {
  4. TreeSet<Integer> evenNumbers = new TreeSet<>();
  5. evenNumbers.add(2);
  6. evenNumbers.add(4);
  7. System.out.println("TreeSet1: " + evenNumbers);
  8. TreeSet<Integer> numbers = new TreeSet<>();
  9. numbers.add(1);
  10. numbers.add(2);
  11. numbers.add(3);
  12. System.out.println("TreeSet2: " + numbers);
  13. // Union of two sets
  14. numbers.addAll(evenNumbers);
  15. System.out.println("Union is: " + numbers);
  16. }
  17. }

输出

  1. TreeSet1: [2, 4]
  2. TreeSet2: [1, 2, 3]
  3. Union is: [1, 2, 3, 4]

交集

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

  1. import java.util.TreeSet;;
  2. class Main {
  3. public static void main(String[] args) {
  4. TreeSet<Integer> evenNumbers = new TreeSet<>();
  5. evenNumbers.add(2);
  6. evenNumbers.add(4);
  7. System.out.println("TreeSet1: " + evenNumbers);
  8. TreeSet<Integer> numbers = new TreeSet<>();
  9. numbers.add(1);
  10. numbers.add(2);
  11. numbers.add(3);
  12. System.out.println("TreeSet2: " + numbers);
  13. // Intersection of two sets
  14. numbers.retainAll(evenNumbers);
  15. System.out.println("Intersection is: " + numbers);
  16. }
  17. }

输出

  1. TreeSet1: [2, 4]
  2. TreeSet2: [1, 2, 3]
  3. Intersection is: [2]

差集

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

  1. import java.util.TreeSet;;
  2. class Main {
  3. public static void main(String[] args) {
  4. TreeSet<Integer> evenNumbers = new TreeSet<>();
  5. evenNumbers.add(2);
  6. evenNumbers.add(4);
  7. System.out.println("TreeSet1: " + evenNumbers);
  8. TreeSet<Integer> numbers = new TreeSet<>();
  9. numbers.add(1);
  10. numbers.add(2);
  11. numbers.add(3);
  12. numbers.add(4);
  13. System.out.println("TreeSet2: " + numbers);
  14. // Difference between two sets
  15. numbers.removeAll(evenNumbers);
  16. System.out.println("Difference is: " + numbers);
  17. }
  18. }

输出

  1. TreeSet1: [2, 4]
  2. TreeSet2: [1, 2, 3, 4]
  3. Difference is: [1, 3]

集合的子集

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

  1. import java.util.TreeSet;
  2. class Main {
  3. public static void main(String[] args) {
  4. TreeSet<Integer> numbers = new TreeSet<>();
  5. numbers.add(1);
  6. numbers.add(2);
  7. numbers.add(3);
  8. numbers.add(4);
  9. System.out.println("TreeSet1: " + numbers);
  10. TreeSet<Integer> primeNumbers = new TreeSet<>();
  11. primeNumbers.add(2);
  12. primeNumbers.add(3);
  13. System.out.println("TreeSet2: " + primeNumbers);
  14. // Check if primeNumbers is subset of numbers
  15. boolean result = numbers.containsAll(primeNumbers);
  16. System.out.println("Is TreeSet2 subset of TreeSet1? " + result);
  17. }
  18. }

输出

  1. TreeSet1: [1, 2, 3, 4]
  2. TreeSet2: [2, 3]
  3. Is TreeSet2 subset of TreeSet1? True

TreeSet的其他方法

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

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


TreeSetHashSet

TreeSetHashSet都实现Set接口。 但是,它们之间存在一些差异。

  • HashSet不同,TreeSet中的元素以某种顺序存储。 这是因为TreeSet也实现了SortedSet接口。
  • TreeSet提供了一些易于导航的方法。 例如first()last()headSet(tailSet()等。这是因为TreeSet也实现了NavigableSet接口。
  • 对于基本操作(例如添加,删除,包含和调整大小),HashSetTreeSet更快。

TreeSet比较器

在以上所有示例中,树集元素都是自然排序的。 但是,我们也可以自定义元素的顺序。

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

  1. import java.util.TreeSet;
  2. import java.util.Comparator;
  3. class Main {
  4. public static void main(String[] args) {
  5. // Creating a tree set with customized comparator
  6. TreeSet<String> animals = new TreeSet<>(new CustomComparator());
  7. animals.add("Dog");
  8. animals.add("Zebra");
  9. animals.add("Cat");
  10. animals.add("Horse");
  11. System.out.println("TreeSet: " + animals);
  12. }
  13. // Creating a comparator class
  14. public static class CustomComparator implements Comparator<String> {
  15. @Override
  16. public int compare(String animal1, String animal2) {
  17. int value = animal1.compareTo(animal2);
  18. // elements are sorted in reverse order
  19. if (value > 0) {
  20. return -1;
  21. }
  22. else if (value < 0) {
  23. return 1;
  24. }
  25. else {
  26. return 0;
  27. }
  28. }
  29. }
  30. }

输出

  1. TreeSet: [Zebra, Horse, Dog, Cat]

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

CustomComparator类实现Comparator接口。

然后,我们覆盖compare()方法。 现在,该方法将以相反的顺序对元素进行排序。

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