Java TreeSet Tutorial with Examples

Java TreeSet class is part of Java’s collections framework. It implements the NavigableSet interface, which in turn extends the SortedSet interface.

The TreeSet class internally uses a TreeMap to store elements. The elements in a TreeSet are sorted according to their natural ordering. You may also provide a custom Comparator to the TreeSet at the time of creation to let it sort the elements based on the supplied comparator.

Java TreeSet in Collection Hierarchy

The SortedSet interface provides functionalities to keep the elements sorted. And the NavigableSet interface provides functionalities to navigate through the SortedSet. For example, finding the element just greater than or just less than a given element, finding the first and last element in the SortedSet etc.

Since the TreeSet class implements NavigableSet interface, it has the functionalities of both - the NavigableSet as well as the SortedSet.

Following are few key points to note about TreeSet in Java -

  • TreeSet cannot contain duplicate elements.

  • The elements in a TreeSet are sorted as per their natural ordering, or based on a custom Comparator that is supplied at the time of creation of the TreeSet.

  • TreeSet cannot contain null value.

  • TreeSet internally uses a TreeMap to store elements.

  • TreeSet class is not thread-safe. You must explicitly synchronize concurrent access to a TreeSet in a multi-threaded environment.

Creating a TreeSet

1. Simple TreeSet

The following example shows how to create a TreeSet and add new elements to it. The TreeSet will be sorted based on the natural ordering of the elements -

import java.util.SortedSet;
import java.util.TreeSet;

public class CreateTreeSetExample {
    public static void main(String[] args) {
        // Creating a TreeSet
        SortedSet<String> fruits = new TreeSet<>();

        // Adding new elements to a TreeSet
        fruits.add("Banana");
        fruits.add("Apple");
        fruits.add("Pineapple");
        fruits.add("Orange");

        System.out.println("Fruits Set : " + fruits);

        // Duplicate elements are ignored
        fruits.add("Apple");
        System.out.println("After adding duplicate element \"Apple\" : " + fruits);

        // This will be allowed because it's in lowercase.
        fruits.add("banana");
        System.out.println("After adding \"banana\" : " + fruits);
    }
}
# Output
Fruits Set : [Apple, Banana, Orange, Pineapple]
After adding duplicate element "Apple" : [Apple, Banana, Orange, Pineapple]
After adding "banana" : [Apple, Banana, Orange, Pineapple, banana]

2. TreeSet with a custom comparator (Case Insensitive Order)

This example shows how to create a TreeSet with a custom comparator that sorts the elements by ignoring the case.

import java.util.Comparator;
import java.util.SortedSet;
import java.util.TreeSet;

public class TreeSetCaseInsensitiveExample {
    public static void main(String[] args) {
        // Creating a TreeSet with a custom Comparator (Case Insensitive Order)
        SortedSet<String> fruits = new TreeSet<>(String.CASE_INSENSITIVE_ORDER);

        /*
            The above TreeSet with the custom Comparator is the concise form of the following:
            SortedSet<String> fruits = new TreeSet<>(new Comparator<String>() {
                @Override
                public int compare(String s1, String s2) {
                    return s1.compareToIgnoreCase(s2);
                }
            });
        */

        // Adding new elements to a TreeSet
        fruits.add("Banana");
        fruits.add("Apple");
        fruits.add("Pineapple");
        fruits.add("Orange");

        System.out.println("Fruits Set : " + fruits);

        // Now, lowercase elements will also be considered as duplicates
        fruits.add("banana");
        System.out.println("After adding \"banana\" : " + fruits);
    }
}
# Output
Fruits Set : [Apple, Banana, Orange, Pineapple]
After adding "banana" : [Apple, Banana, Orange, Pineapple]

3. Tree Set with a custom Comparator (Descending order)

The example below demonstrates how to create a TreeSet with a custom comparator that sorts the elements in descending order -

import java.util.Comparator;
import java.util.SortedSet;
import java.util.TreeSet;

public class TreeSetDescendingOrderExample {
    public static void main(String[] args) {
        // Creating a TreeSet with a custom Comparator (Descending  Order)
        SortedSet<String> fruits = new TreeSet<>(Comparator.reverseOrder());

        /*
            The above TreeSet with the custom Comparator is the concise form of the following:
            SortedSet<String> fruits = new TreeSet<>(new Comparator<String>() {
                @Override
                public int compare(String s1, String s2) {
                    return s2.compareTo(s1);
                }
            });
        */

        // Adding new elements to a TreeSet
        fruits.add("Banana");
        fruits.add("Apple");
        fruits.add("Pineapple");
        fruits.add("Orange");

        System.out.println("Fruits Set : " + fruits);
    }
}
# Output
Fruits Set : [Pineapple, Orange, Banana, Apple]

Accessing the elements of a TreeSet

The example below shows how to

  • Find the size of a TreeSet.
  • Check if an element exists in a TreeSet.
  • Find the first element in the TreeSet.
  • Find the last element in the TreeSet.
  • Find the element just higher than the given element in the TreeSet.
  • Find the element just lower than the given element in the TreeSet.
import java.util.TreeSet;

public class AccessTreeSetElementsExample {
    public static void main(String[] args) {
        TreeSet<String> students = new TreeSet<>(String.CASE_INSENSITIVE_ORDER);

        students.add("Julia");
        students.add("Robert");
        students.add("Mark");
        students.add("Steven");

        System.out.println("Students TreeSet : " + students);

        // Finding the size of a TreeSet
        System.out.println("Number of elements in the TreeSet : " + students.size());

        // Check if an element exists in the TreeSet
        String name = "Julia";
        if(students.contains(name)) {
            System.out.println("TreeSet contains the element : " + name);
        } else {
            System.out.println("TreeSet does not contain the element : " + name);
        }

        // Navigating through the TreeSet
        System.out.println("First element : " + students.first());
        System.out.println("Last element : " + students.last());

        name = "Robert";
        System.out.println("Element just greater than "  + name + " : " + students.higher(name));
        System.out.println("Element just lower than "  + name + " : " + students.lower(name));

    }
}
# Output
Students TreeSet : [Julia, Mark, Robert, Steven]
Number of elements in the TreeSet : 4
TreeSet contains the element : Julia
First element : Julia
Last element : Steven
Element just greater than Robert : Steven
Element just lower than Robert : Mark

Removing elements from a TreeSet

This example shows how to

  • Remove an element from a TreeSet.
  • Remove all elements that satisfy a given predicate.
  • Remove the first element of the TreeSet.
  • Remove the last element of the TreeSet.
import java.util.TreeSet;

public class RemoveTreeSetElementsExample {
    public static void main(String[] args) {
        TreeSet<Integer> numbers = new TreeSet<>();

        numbers.add(10);
        numbers.add(15);
        numbers.add(20);
        numbers.add(25);
        numbers.add(30);
        numbers.add(42);
        numbers.add(49);
        numbers.add(50);

        System.out.println("numbers TreeSet : " + numbers);

        // Remove an element from the TreeSet
        boolean isRemoved = numbers.remove(49);
        if(isRemoved) {
            System.out.println("After Removing 49 : " + numbers);
        }

        // Remove all elements divisible by 3
        numbers.removeIf(number -> number % 3 == 0);
        System.out.println("After removeIf() : " + numbers);


        // Retrieve and remove the first element from the TreeSet
        Integer num = numbers.pollFirst();
        System.out.println("Removed first element " + num + " from the TreeSet : " + numbers);

        // Retrieve and remove the last element from the TreeSet
        num = numbers.pollLast();
        System.out.println("Removed last element " + num + " from the TreeSet : " + numbers);
    }
}
# Output
numbers TreeSet : [10, 15, 20, 25, 30, 42, 49, 50]
After Removing 49 : [10, 15, 20, 25, 30, 42, 50]
After removeIf() : [10, 20, 25, 50]
Removed first element 10 from the TreeSet : [20, 25, 50]
Removed last element 50 from the TreeSet : [20, 25]

TreeSet with user defined objects

The example in this section shows how to create a TreeSet of user defined objects.

Since the TreeSet needs to keep the objects sorted, you must either implement the Comparable interface in the user defined class and provide the implementation for the compareTo() function, or provide a custom Comparator at the time of creation of the TreeSet.

import java.util.Comparator;
import java.util.Objects;
import java.util.SortedSet;
import java.util.TreeSet;

class Employee implements Comparable<Employee> {
    private int id;
    private String name;

    public Employee(int id, String name) {
        this.id = id;
        this.name = name;
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    // Two Employees are equal if their IDs are equal
    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Employee employee = (Employee) o;
        return id == employee.id;
    }

    @Override
    public int hashCode() {
        return Objects.hash(id);
    }

    // Compare employees based on their IDs
    @Override
    public int compareTo(Employee employee) {
        return this.getId() - employee.getId();
    }

    @Override
    public String toString() {
        return "Employee{" +
                "id=" + id +
                ", name='" + name + '\'' +
                '}';
    }
}


public class TreeSetUserDefinedObjectExample {
    public static void main(String[] args) {
        // Creating a TreeSet of User Defined Objects.

        /*
           The requirement for a TreeSet of user defined objects is that

           1. Either the class should implement the Comparable interface and provide
              the implementation for the compareTo() function.
           2. Or you should provide a custom Comparator while creating the TreeSet.
        */

        SortedSet<Employee> employees = new TreeSet<>();

        // TreeSet uses the compareTo() method of the Employee class to compare two employees and sort them
        employees.add(new Employee(1010, "Rajeev"));
        employees.add(new Employee(1005, "Sachin"));
        employees.add(new Employee(1008, "Chris"));

        System.out.println("Employees (sorted based on Employee class's compareTo() function)");
        System.out.println(employees);

        // Providing a Custom Comparator (This comparator compares the employees based on their Name)
        employees = new TreeSet<>(Comparator.comparing(Employee::getName));

        employees.add(new Employee(1010, "Rajeev"));
        employees.add(new Employee(1005, "Sachin"));
        employees.add(new Employee(1008, "Chris"));

        System.out.println("\nEmployees (sorted based on the supplied Comparator)");
        System.out.println(employees);

    }
}
# Output
Employees (sorted based on Employee class's compareTo() function)
[Employee{id=1005, name='Sachin'}, Employee{id=1008, name='Chris'}, Employee{id=1010, name='Rajeev'}]

Employees (sorted based on the supplied Comparator)
[Employee{id=1008, name='Chris'}, Employee{id=1010, name='Rajeev'}, Employee{id=1005, name='Sachin'}]

Conclusion

Congratulations folks! In this article, you learned what is a TreeSet in Java, how to create a TreeSet, how to pass a custom comparator to the TreeSet to alter the sorting order of the elements, how to access the elements of a TreeSet, how to remove elements from a TreeSet, and how to create a TreeSet of user defined objects.

Thanks for reading. See you in the next post.