Java Collections.checkedSortedSet 方法
上次修改时间:2025 年 4 月 20 日
Collections.checkedSortedSet
方法是 Java Collections Framework 的一部分。它为 SortedSet 实现提供运行时类型安全。此方法返回指定排序集合的动态类型安全视图。
任何尝试插入错误类型元素的操作都会立即导致 ClassCastException
。 这有助于及早检测编程错误,而不是允许它们传播。 如果指定的集合是可序列化的,则返回的集合将是可序列化的。
Collections.checkedSortedSet 概述
当处理遗留代码或无法在编译时保证类型安全时,checkedSortedSet
方法特别有用。 它包装现有的 SortedSet 并在运行时强制执行类型检查。
该方法的签名为:static <E> SortedSet<E> checkedSortedSet(SortedSet<E> s, Class<E> type)
。 它接受要包装的排序集合以及它应包含的元素的类型。
checkedSortedSet 的基本用法
此示例演示了 Collections.checkedSortedSet
的基本用法。 我们创建一个字符串 TreeSet 并使用类型安全视图包装它。 该示例显示了有效和无效的操作。
package com.zetcode; import java.util.Collections; import java.util.SortedSet; import java.util.TreeSet; public class BasicCheckedSortedSet { public static void main(String[] args) { SortedSet<String> names = new TreeSet<>(); names.add("Alice"); names.add("Bob"); // Create type-safe view SortedSet<String> checkedNames = Collections.checkedSortedSet(names, String.class); // Valid operation checkedNames.add("Charlie"); System.out.println("Valid addition: " + checkedNames); try { // Invalid operation - adding wrong type checkedNames.add(42); // Integer instead of String } catch (ClassCastException e) { System.out.println("\nCaught exception: " + e.getMessage()); } } }
此代码创建一个字符串的 TreeSet
并使用 Collections.checkedSortedSet
包装它。 类型安全视图允许添加有效的 String 元素,但会为无效类型抛出 ClassCastException
。
输出显示成功添加了“Charlie”,以及尝试添加 Integer 时捕获的异常。 这演示了运行时类型检查。
使用遗留代码
在处理不使用泛型的遗留代码时,checkedSortedSet
特别有用。 此示例演示了如何防止此类场景中的类型不安全操作。
package com.zetcode; import java.util.Collections; import java.util.SortedSet; import java.util.TreeSet; public class LegacyCodeProtection { @SuppressWarnings({"unchecked", "rawtypes"}) public static void main(String[] args) { // Legacy code without generics SortedSet rawSet = new TreeSet(); rawSet.add("Apple"); rawSet.add("Banana"); // Create type-safe view SortedSet<String> safeSet = Collections.checkedSortedSet(rawSet, String.class); // Pass to legacy method legacyMethod(rawSet); System.out.println("After legacy method: " + safeSet); try { // Now try to use the safe view safeSet.add("Cherry"); // Valid safeSet.add(123); // Invalid } catch (ClassCastException e) { System.out.println("\nCaught exception: " + e.getMessage()); } } @SuppressWarnings("rawtypes") private static void legacyMethod(SortedSet set) { // Legacy method might add wrong types set.add(42); // This will succeed in raw set } }
此示例演示了 checkedSortedSet
如何帮助识别遗留代码中的类型安全问题。 原始集合允许添加任何类型,但是类型安全视图会在使用时捕获无效的添加。
输出显示遗留方法成功地将 Integer 添加到原始集合,但尝试通过类型安全视图添加 Integer 会抛出异常。 这有助于定位类型安全问题。
与其他 Collections 方法结合使用
此示例显示了如何将 checkedSortedSet
与其他 Collections 实用程序方法结合使用。 我们创建一个排序集合的不可修改的类型安全视图。
package com.zetcode; import java.util.Collections; import java.util.SortedSet; import java.util.TreeSet; public class CombinedCollectionsMethods { public static void main(String[] args) { SortedSet<Integer> numbers = new TreeSet<>(); numbers.add(10); numbers.add(20); numbers.add(30); // Create type-safe and unmodifiable view SortedSet<Integer> safeUnmodifiableSet = Collections.unmodifiableSortedSet( Collections.checkedSortedSet(numbers, Integer.class)); System.out.println("Initial set: " + safeUnmodifiableSet); try { // Attempt modification through unmodifiable view safeUnmodifiableSet.add(40); } catch (UnsupportedOperationException e) { System.out.println("\nCaught UnsupportedOperationException: " + e.getMessage()); } try { // Attempt to add wrong type to original set numbers.add("Not a number"); } catch (ClassCastException e) { System.out.println("\nCaught ClassCastException: " + e.getMessage()); } } }
此代码将 checkedSortedSet
与 unmodifiableSortedSet
结合使用,以创建一个既类型安全又不可修改的视图。 该示例演示了类型安全和不可变性保护。
输出显示尝试通过不可修改的视图修改集合的尝试被捕获,并且尝试将错误类型的元素添加到原始集合的尝试也被捕获。 这演示了分层集合保护。
使用自定义比较器
checkedSortedSet
可与使用自定义比较器的排序集合一起使用。 此示例演示了具有不区分大小写的字符串比较器的排序集合中的类型检查。
package com.zetcode; import java.util.Collections; import java.util.Comparator; import java.util.SortedSet; import java.util.TreeSet; public class CustomComparatorExample { public static void main(String[] args) { // Create sorted set with case-insensitive comparator SortedSet<String> caseInsensitiveSet = new TreeSet<>( String.CASE_INSENSITIVE_ORDER); caseInsensitiveSet.add("Apple"); caseInsensitiveSet.add("banana"); // Create type-safe view SortedSet<String> checkedSet = Collections.checkedSortedSet(caseInsensitiveSet, String.class); System.out.println("Original set: " + checkedSet); // Adding with different case works due to comparator checkedSet.add("APPLE"); System.out.println("After adding 'APPLE': " + checkedSet); try { // Adding wrong type fails checkedSet.add(42); } catch (ClassCastException e) { System.out.println("\nCaught ClassCastException: " + e.getMessage()); } } }
此示例表明 checkedSortedSet
可与使用自定义比较器的排序集合一起使用。 类型检查的执行独立于排序逻辑。
输出表明不区分大小写的比较器允许添加“APPLE”(尽管它不会出现两次,因为它等于“Apple”),而尝试添加 Integer 会被类型检查捕获。
使用 checkedSortedSet 进行序列化
如果支持集合是可序列化的,则 checkedSortedSet
返回的集合是可序列化的。 此示例演示了类型安全排序集合的序列化和反序列化。
package com.zetcode; import java.io.*; import java.util.Collections; import java.util.SortedSet; import java.util.TreeSet; public class SerializationExample { public static void main(String[] args) { String filename = "checkedset.ser"; // Create and serialize a checked sorted set try (ObjectOutputStream oos = new ObjectOutputStream( new FileOutputStream(filename))) { SortedSet<Double> numbers = new TreeSet<>(); numbers.add(3.14); numbers.add(2.71); SortedSet<Double> checkedNumbers = Collections.checkedSortedSet(numbers, Double.class); oos.writeObject(checkedNumbers); System.out.println("Serialized set: " + checkedNumbers); } catch (IOException e) { e.printStackTrace(); } // Deserialize the checked sorted set try (ObjectInputStream ois = new ObjectInputStream( new FileInputStream(filename))) { @SuppressWarnings("unchecked") SortedSet<Double> deserialized = (SortedSet<Double>) ois.readObject(); System.out.println("Deserialized set: " + deserialized); // Verify type safety still works try { deserialized.add("Not a number"); } catch (ClassCastException e) { System.out.println("\nCaught ClassCastException: " + e.getMessage()); } } catch (IOException | ClassNotFoundException e) { e.printStackTrace(); } } }
此示例演示了类型安全包装器在序列化和反序列化后保持其类型检查功能。 序列化的集合保留其元素和类型安全约束。
输出显示了序列化之前和反序列化之后的集合,以及尝试添加无效类型时捕获的异常。 这证实了类型安全通过序列化得以维护。
性能注意事项
虽然 checkedSortedSet
提供了有价值的类型安全,但它确实增加了一点性能开销。 此示例演示了如何衡量类型检查包装的影响。
package com.zetcode; import java.util.Collections; import java.util.SortedSet; import java.util.TreeSet; public class PerformanceComparison { public static void main(String[] args) { final int ELEMENT_COUNT = 100000; final int TEST_RUNS = 100; SortedSet<Integer> regularSet = new TreeSet<>(); SortedSet<Integer> checkedSet = Collections.checkedSortedSet(new TreeSet<>(), Integer.class); // Test regular set performance long regularTime = timeAddOperations(regularSet, ELEMENT_COUNT, TEST_RUNS); // Test checked set performance long checkedTime = timeAddOperations(checkedSet, ELEMENT_COUNT, TEST_RUNS); System.out.println("Regular set time: " + regularTime + " ms"); System.out.println("Checked set time: " + checkedTime + " ms"); System.out.println("Overhead: " + ((double)(checkedTime - regularTime)/regularTime * 100) + "%"); } private static long timeAddOperations(SortedSet<Integer> set, int count, int runs) { long totalTime = 0; for (int i = 0; i < runs; i++) { set.clear(); long start = System.currentTimeMillis(); for (int j = 0; j < count; j++) { set.add(j); } totalTime += System.currentTimeMillis() - start; } return totalTime / runs; } }
此代码比较了常规 TreeSet
与类型安全包装版本的性能。 该测试测量了将元素添加到两个集合所花费的时间,并对多次运行取平均值以提高准确性。
输出显示了绝对时间以及类型检查引入的百分比开销。 虽然开销通常很小,但在对性能至关重要的应用程序中需要考虑它。
来源
Java Collections.checkedSortedSet 文档
在本文中,我们深入探讨了 Collections.checkedSortedSet
方法。 我们涵盖了基本用法、遗留代码集成、与其他实用程序的组合、自定义比较器、序列化和性能。
作者
列出所有Java教程。