Java 的 SortedSet 接口(即 java.util.SortedSet)是 java.util.Set 接口的子类型。它的行为与普通 Set 类似,核心区别在于其包含的元素在内部会被排序。这意味着,当你迭代 SortedSet 中的元素时,元素会按照预设的排序规则依次出现。
在 Java 集合 API 中,SortedSet 接口仅有一个核心实现类,即 java.util.TreeSet 类。尽管 java.util.concurrent 包中也存在该接口的实现类,但在本系列介绍中,暂不涉及并发相关工具类的内容。
以下是创建一个 TreeSet 实例的示例:
SortedSet sortedSet = new TreeSet<>(); sortedSet.add("about"); sortedSet.add("sport"); sortedSet.add("dance"); for(Object obj : sortedSet) { // 强制类型转换 String val = (String) obj; System.out.println(val); }
当你声明一个类型为 SortedSet 的变量时,你可以为其设置一个泛型类型。例如:
SortedSet<String> set = new TreeSet<>();
上述代码,SortedSet 现在只能包含 String 对象作为元素。这意味着,除其他方面外,你不再需要将从 SortedSet 中获取的对象强制转换为 String 类型。例如:
SortedSet<String> sortedSet = new TreeSet<>(); sortedSet.add("about"); sortedSet.add("sport"); sortedSet.add("dance"); for(String val : sortedSet) { // 这里不需要进行强制转换 System.out.println(val); }
除了无参构造函数,你可以向 TreeSet 的构造函数传递一个 Comparator(即 java.util.Comparator 的实现)。这个 Comparator 将决定 TreeSet 中元素的排序方式。例如:
SortedSet<String> set = new TreeSet<>(new Comparator<String>(){ @Override public int compare(String o1, String o2) { return o1.compareTo(o2); } }); set.add("about"); set.add("sport"); set.add("dance"); System.out.println(set); // [about, dance, sport]
Java 的 SortedSet 采用默认排序方式为元素的自然排序。要使 SortedSet 能够确定元素的自然顺序,元素必须实现 java.lang.Comparable 接口。
若元素未实现 Comparable 接口,则不具备自然排序能力。这种情况下,创建 SortedSet 时必须传入一个 Comparator 实现 —— TreeSet 类的构造函数支持接收 Comparator 参数。例如:
SortedSet<String> set = new TreeSet<>(); set.add("about"); set.add("sport"); set.add("dance"); System.out.println(set); // [about, dance, sport]
手动传递 Comparator,例如:
Comparator<String> comparator = new Comparator<String>(){ @Override public int compare(String o1, String o2) { return o2.compareTo(o1); } }; SortedSet<String> set = new TreeSet<>(comparator); set.add("about"); set.add("sport"); set.add("dance"); System.out.println(set); // [sport, dance, about]
如果你使用比较器(Comparator)创建了 SortedSet,那么你可以通过 SortedSet 的 comparator() 方法获取该比较器。例如:
Comparator<String> comparator = new Comparator<String>(){ @Override public int compare(String o1, String o2) { return o2.compareTo(o1); } }; SortedSet<String> set = new TreeSet<>(comparator); set.add("about"); set.add("sport"); set.add("dance"); System.out.println("comparator=" + comparator); System.out.println("comparator()=" + set.comparator()); //comparator=com.hxstrive.java_collection.set.SortedSetDemo$1@3d075dc0 //comparator()=com.hxstrive.java_collection.set.SortedSetDemo$1@3d075dc0
向 SortedSet 中添加元素的方式与向普通的 Set 中添加元素的方式相同,都是通过其 add()方法。例如:
SortedSet<String> set = new TreeSet<>(); set.add("about"); set.add("sport"); set.add("dance");
要从 SortedSet 中移除一个元素,你可以调用它的 remove() 方法,并将需要移除的元素作为参数传入。例如:
SortedSet<String> set = new TreeSet<>(); set.add("about"); set.add("sport"); set.add("dance"); System.out.println("移除前 " + set); //移除前 [about, dance, sport] set.remove("sport"); System.out.println("移除后 " + set); //移除后 [about, dance]
你可以通过调用 SortedSet 的 first() 方法,按照其排序顺序获取 SortedSet 的第一个元素。例如:
SortedSet<String> set = new TreeSet<>(); set.add("about"); set.add("sport"); set.add("dance"); String first = set.first(); System.out.println("first=" + first); //first=about
你可以通过调用 SortedSet 的 last() 方法,按照其排序顺序获取 SortedSet 的最后一个元素。例如:
SortedSet<String> set = new TreeSet<>(); set.add("about"); set.add("sport"); set.add("dance"); String last = set.last(); System.out.println("last=" + last); //last=sport
迭代 SortedSet 中元素的方式,与迭代普通 Set 的方式一致:调用 SortedSet 的 iterator() 方法,该方法会返回一个 Iterator 实例,通过这个迭代器即可遍历元素(需注意,SortedSet 的迭代器会按预设排序顺序返回元素)。例如:
SortedSet<String> set = new TreeSet<>(); set.add("about"); set.add("sport"); set.add("dance"); Iterator<String> iterator = set.iterator(); while(iterator.hasNext()) { System.out.println(iterator.next()); // 打印每个 }
运行结果:
about dance sport
Java 的 SortedSet 接口提供了 headSet() 方法,该方法会依据集合的排序规则,返回一个新的 SortedSet,其中包含原集合中所有小于(即排序位置在其之前)给定参数值的元素。例如:
SortedSet<String> sortedSet = new TreeSet<>(); sortedSet.add("a"); sortedSet.add("b"); sortedSet.add("c"); sortedSet.add("d"); sortedSet.add("e"); SortedSet<String> headSet = sortedSet.headSet("c"); System.out.println(headSet); //[a, b]
运行此代码后,headSet 将包含元素 "a" 和 "b",因为这两个元素小于(位于……之前)传递给 headSet() 方法的参数值 "c"。
Java 的 SortedSet 接口提供了 tailSet() 方法,该方法会依据集合的排序规则,返回一个新的 SortedSet,其中包含原集合中所有大于或等于(即排序位置在其之后或与之相同)给定参数值的元素。例如:
SortedSet<String> sortedSet = new TreeSet<>(); sortedSet.add("a"); sortedSet.add("b"); sortedSet.add("c"); sortedSet.add("d"); sortedSet.add("e"); SortedSet<String> tailSet = sortedSet.tailSet("c"); System.out.println(tailSet); //[c, d, e]
运行此代码后,tailSet 将包含元素“c”、“d”和“e”,因为这三个元素都大于或等于(位于其后)传递给 tailSet() 方法的参数值“c”。
Java 的 SortedSet 接口提供了 subSet() 方法,该方法会返回一个新的 SortedSet,作为调用此方法的原集合的子集。subSet() 方法接收两个参数,用于界定返回子集所包含的元素范围 —— 依据集合的排序规则,返回的子集将包含所有大于或等于第一个参数,且小于第二个参数的元素。例如:
SortedSet<String> sortedSet = new TreeSet<>(); sortedSet.add("a"); sortedSet.add("b"); sortedSet.add("c"); sortedSet.add("d"); sortedSet.add("e"); SortedSet<String> subSet = sortedSet.subSet("c", "e"); System.out.println(subSet); //[c, d]
运行此代码后,子集(subSet)将包含元素“c”和“d”,因为这两个元素都大于或等于“c”(第一个参数),且小于“e”(第二个参数)。