ZetCode

Java Collections.checkedSortedSet Method

Last modified: April 20, 2025

The Collections.checkedSortedSet method is part of Java's Collections Framework. It provides runtime type safety for SortedSet implementations. This method returns a dynamically type-safe view of the specified sorted set.

Any attempt to insert an element of the wrong type will result in an immediate ClassCastException. This helps detect programming errors early rather than allowing them to propagate. The returned set will be serializable if the specified set is serializable.

Collections.checkedSortedSet Overview

The checkedSortedSet method is particularly useful when working with legacy code or when type safety cannot be guaranteed at compile time. It wraps an existing SortedSet and enforces type checking at runtime.

The method signature is: static <E> SortedSet<E> checkedSortedSet(SortedSet<E> s, Class<E> type). It takes the sorted set to wrap and the type of elements it should contain.

Basic Usage of checkedSortedSet

This example demonstrates the basic usage of Collections.checkedSortedSet. We create a TreeSet of Strings and wrap it with a type-safe view. The example shows both valid and invalid operations.

BasicCheckedSortedSet.java
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());
        }
    }
}

This code creates a TreeSet of Strings and wraps it with Collections.checkedSortedSet. The type-safe view allows adding valid String elements but throws ClassCastException for invalid types.

The output shows the successful addition of "Charlie" and the caught exception when trying to add an Integer. This demonstrates the runtime type checking.

Working with Legacy Code

The checkedSortedSet is particularly useful when dealing with legacy code that doesn't use generics. This example shows how to protect against type-unsafe operations in such scenarios.

LegacyCodeProtection.java
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
    }
}

This example demonstrates how checkedSortedSet can help identify type safety issues in legacy code. The raw set allows adding any type, but the type-safe view catches invalid additions when used.

The output shows that the legacy method successfully added an Integer to the raw set, but attempting to add an Integer through the type-safe view throws an exception. This helps localize type safety issues.

Combining with Other Collections Methods

This example shows how checkedSortedSet can be combined with other Collections utility methods. We create an unmodifiable type-safe view of a sorted set.

CombinedCollectionsMethods.java
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());
        }
    }
}

This code combines checkedSortedSet with unmodifiableSortedSet to create a view that is both type-safe and unmodifiable. The example demonstrates both type safety and immutability protection.

The output shows that attempts to modify the set through the unmodifiable view are caught, as are attempts to add elements of the wrong type to the original set. This demonstrates layered collection protections.

Using with Custom Comparators

The checkedSortedSet works with sorted sets that use custom comparators. This example demonstrates type checking in a sorted set with a case-insensitive string comparator.

CustomComparatorExample.java
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());
        }
    }
}

This example shows that checkedSortedSet works with sorted sets that use custom comparators. The type checking is performed independently of the sorting logic.

The output demonstrates that the case-insensitive comparator allows "APPLE" to be added (though it doesn't appear twice due to being equal to "Apple"), while attempting to add an Integer is caught by the type checking.

Serialization with checkedSortedSet

The set returned by checkedSortedSet is serializable if the backing set is serializable. This example demonstrates serialization and deserialization of a type-safe sorted set.

SerializationExample.java
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();
        }
    }
}

This example demonstrates that the type-safe wrapper maintains its type checking capabilities after serialization and deserialization. The serialized set preserves both its elements and its type safety constraints.

The output shows the set before serialization and after deserialization, followed by the caught exception when attempting to add an invalid type. This confirms that type safety is maintained through serialization.

Performance Considerations

While checkedSortedSet provides valuable type safety, it does add a small performance overhead. This example demonstrates how to measure the impact of the type checking wrapper.

PerformanceComparison.java
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;
    }
}

This code compares the performance of a regular TreeSet with a type-safe wrapped version. The test measures the time taken to add elements to both sets, averaging over multiple runs for accuracy.

The output shows the absolute times and the percentage overhead introduced by the type checking. While the overhead is typically small, it's important to consider in performance-critical applications.

Source

Java Collections.checkedSortedSet Documentation

In this article, we've explored the Collections.checkedSortedSet method in depth. We've covered basic usage, legacy code integration, combination with other utilities, custom comparators, serialization, and performance.

Author

My name is Jan Bodnar, and I am a dedicated programmer with many years of experience in the field. I began writing programming articles in 2007 and have since authored over 1,400 articles and eight e-books. With more than eight years of teaching experience, I am committed to sharing my knowledge and helping others master programming concepts.

List all Java tutorials.