Skip to content

Java TreeSet with example

  • by
Java TreeSet example

1. Overview

In this article, we will learn about the Java TreeSet with an example. TreeSet extends AbstractSet and implements the NavigableSet interface.

To learn about Java collections, refer to this article.

2. Java TreeSet

A TreeSet creates a collection that uses a tree for storage. It stores the elements in sorted, ascending order and prevents any duplicates. Access and retrieval times are quite fast, which makes the TreeSet an excellent choice when storing large amounts of sorted information that must be retrieved quickly.

It works just like the Collections.sort method.

A TreeSet is similar to HashSet in that:

  1. Prevents duplicates
  2. Keeps the list sorted automatically
  3. Does not accept null values

The downside to TreeSet is that if you don’t need sorting, you’re still paying for it with a small performance hit. But you’ll probably find that the hit is almost impossible to notice for most apps.

2.1. Java TreeSet constructors

A TreeSet is a generic class that has this declaration:

Class TreeSet<E>

Here, E specifies the type of objects that the set will hold.

A TreeSet has the following constructors:

TreeSet( ) TreeSet(Collection c) TreeSet(Comparator comp) TreeSet(SortedSet ss) 

2.2. Java TreeSet Sorting order

By default, the TreeSet uses each object’s compareTo method for the sort. But you have the option of passing a Comparator to the TreeSet constructor, to have the TreeSet use that instead.

To use a TreeSet, one of these things must be true:

  1. The elements in the list must be of a type that implements Comparable.
  2. Specify the comparator as an argument to the TreeSet’s overloaded constructor

For example, the following code adds the Employee elements to the TreeSet. Since the Employee class is not implementing the comparable, this won’t work.

@Test
void treeSetEmployeeExample() {
	TreeSet<Student> treeSet = new TreeSet<Student>();
	treeSet.add(new Student(11020, "John", 99));
	treeSet.add(new Student(11023, "Kevin", 84));
	treeSet.add(new Student(11025, "Chris", 43));
	treeSet.add(new Student(11029, "Elvis", 23));
	treeSet.add(new Student(11030, "John", 78));

	System.out.println(treeSet);
}

class Student  {
	private long studentId;
	private String studentName;
	private int marks;
	Student(long studentId, String studentName, int marks) {
		this.studentId = studentId;
		this.studentName = studentName;
		this.marks = marks;
	}
}

If you execute the above code, it results in the ClassCastException.

java.lang.ClassCastException: class com.tedblob.interview.InterviewApplicationTests$Student cannot be cast to class java.lang.Comparable (com.tedblob.interview.InterviewApplicationTests$Student is in unnamed module of loader 'app'; java.lang.Comparable is in module java.base of loader 'bootstrap')

	at java.base/java.util.TreeMap.compare(TreeMap.java:1563)

You can prevent this by either implementing a Comparable interface.

class Student implements Comparable {
	
	private long studentId;
	private String studentName;
	private int marks;

	Student(long studentId, String studentName, int marks) {
		this.studentId = studentId;
		this.studentName = studentName;
		this.marks = marks;
	}

	@Override
	public int compareTo(Object o) {
		Student obj = (Student) o;
		return compare(this.marks, obj.marks);
	}

	private int compare(int thisObj, int obj) {
		return (thisObj < obj) ? 1 : ((thisObj == obj) ? 0 : -1);
	}

	@Override
	public String toString() {
		return "Student{" +
				"studentId=" + studentId +
				", studentName='" + studentName + '\'' +
				", marks=" + marks +
				'}';
	}
}

Alternatively, you can pass a Comparator to the TreeSet overloaded constructor.

TreeSet<Student> treeSet = new TreeSet<Student>(new Comparator<Student>() {
			@Override
			public int compare(Student o1, Student o2) {
				return (o1.getMarks() < o2.getMarks()) ? 1 : ((o1.getMarks() == o2.getMarks()) ? 0 : -1);
			}
		});

3. Java TreeSet String example

Look at the following example. We have created an empty TreeSet with the default no-arg constructor. Later, pushed the elements to it using the add method.

@Test
void treeSetStringExample() {
	TreeSet<String> treeSet = new TreeSet<String>();
	treeSet.add("Z");
	treeSet.add("B");
	treeSet.add("S");
	treeSet.add("A");
	treeSet.add("E");
	treeSet.add("G");

	System.out.println(treeSet);
}

If you execute the above test case, it prints the elements in ascending order.

[A, B, E, G, S, Z]

It worked because the Java String implements the Comparable interface and its compareTo method.

4. Java TreeSet prevents duplicates

Since the TreeSet is an implementation of the Set interface, it prevents duplicates.

Look at the below code. Though we added the same element "A" twice, it appears only once.

@Test
void treeSetStringExample() {
	TreeSet<String> treeSet = new TreeSet<String>();
	treeSet.add("A");
	treeSet.add("A");

	System.out.println(treeSet);
}

5. Java TreeSet with null

As mentioned earlier, a TreeSet cannot accept null values.

@Test
void treeSetWithNullExample() {
	TreeSet<String> treeSet = new TreeSet<String>();
	treeSet.add("Z");
	treeSet.add(null);
}

By default, the Comparable interface is used internally by the TreeSet to sort the elements. Now in the Comparable Interface, the compareTo() method is used to compare one value with another to sort the elements. 

So because of this purpose, null has no value, that’s why the compareTo() method cannot compare null with another value, giving a NullPointerException.

java.lang.NullPointerException
	at java.base/java.util.Objects.requireNonNull(Objects.java:208)
	at java.base/java.util.TreeMap.put(TreeMap.java:801)
	at java.base/java.util.TreeMap.put(TreeMap.java:534)
	at java.base/java.util.TreeSet.add(TreeSet.java:255)

However, you can change this behavior by using a custom comparator that handles the null values. Once you handle null in the comparator, the TreeSet won’t throw NullPointerException.

@Test
void treeSetWithNullExample() {
	TreeSet<String> treeSet = new TreeSet<String>(new Comparator<String>() {
	@Override
	public int compare(String o1, String o2) {
		if (o1 == null) return 1;
		if (o2 == null) return -1;
		return o1.compareTo(o2);
	}
	});
	treeSet.add("Z");
	treeSet.add(null);
	System.out.println(treeSet);
}

If you execute the above test case, it shows the following output.

[Z, null]

6. Conclusion

To sum up, we have learned the Java TreeSet along with an example. You can find code samples in our GitHub repository.

Leave a Reply

Your email address will not be published. Required fields are marked *