Java TreeSet

In this tutorial, we will learn about functionality of java.util.TreeSet, its use cases along with working examples which includes user-defined class elements.

TreeSet class

In Java, java.util.TreeSet is a class from collections framework which is an implementation of set. As compared to the other set implemented classes TreeSet provides custom ordering by using Comparator or Comparable interface implementations. But this needs to specified at the time of creating a TreeSet object, if do not specify any order it will follow the order in which Comparable interface implemented by element class. If Comparable class is not implemented will cause an exception during runtime.

TreeSet provides guaranteed or constant performance log(n) for adding elements, removing, and checking element contains in set. TreeSet is backed by the TreeMap, which is an implementation of NavigableMap.

It is important note that TreeSet is not a thread-safe implementations, which means multiple threads can access concurrently.

TreeSet use cases:

  1. Eliminates duplicates.
  2. Provides custom order.
  3. Can be used where priority-based ordering is necessary.

In the following examples, we will cover one without specifying the order which elements should be displayed and another one with custom order of elements.

TreeSet example without order:

CopiedCopy Code
import java.util.TreeSet;
public class TreeSetExample {
	public static void main(String[] args) {
		TreeSet<String> treeSet = new TreeSet<>();
		treeSet.add("One");
		treeSet.add("Two");
		treeSet.add("Three");
		treeSet.add("Four");
		treeSet.add("Five");
		System.out.println(treeSet);
	}
}

Output:

[Five, Four, One, Three, Two]

Explanation:

In the above example, created a TreeSet class without specifying any order(no specification of comparator has been provided) and added five elements of String type. As we know String class implemented Comparable interface which follows natural order and while printing it followed natural order and printed elements in same(Alphabetical) order.

TreeSet example with comparator order:

In this example, we will create user-defined class and will add its elements to the TreeSet by specifying the Comparator of user-defined class.

CopiedCopy Code
import java.util.Comparator;
import java.util.TreeSet;
public class TreeSetUserDefined {
	public static void main(String[] args) {
		// We implemented Comparator of Albums on AlbumsComparator
		// passing AlbumsComparator to TreeSet class
		TreeSet<Albums> treeSet = new TreeSet<>(new AlbumsComparator());
		Albums albm1 = new Albums("Abilene", "Bluegrass");
		Albums albm2 = new Albums("Above And Beyond", "Bluegrass");
		Albums albm3 = new Albums("Acadian Driftwood", "Roots");
		Albums albm4 = new Albums("Acquiesce", "Pop");
		treeSet.add(albm1);
		treeSet.add(albm2);
		treeSet.add(albm3);
		treeSet.add(albm4);
		// In AlbumsComparator we used custom compare method to reverse natural order
		System.out.println(treeSet);
	}
	static class AlbumsComparator implements Comparator<Albums> {
		// To specify order compare method is overriden
		@Override
		public int compare(TreeSetUserDefined.Albums o1, TreeSetUserDefined.Albums o2) {
			// o2 object is compared with o1, it will reverse natural order
			return o2.song.compareTo(o1.song);
		}
	}
	static class Albums {
		public String song;
		public String genre;
		public Albums(String song, String albumName) {
			this.song = song;
			this.genre = albumName;
		}
		// hashCode overridden to find duplicates
		@Override
		public int hashCode() {
			final int prime = 31;
			int result = 1;
			result = prime * result + ((genre == null) ? 0 : genre.hashCode());
			result = prime * result + ((song == null) ? 0 : song.hashCode());
			return result;
		}
		// equals overridden to find duplicates
		@Override
		public boolean equals(Object obj) {
			Albums other = (Albums) obj;
			if (genre.equals(other.genre) && song.equals(other.song))
				return true;
			return false;
		}
		@Override
		public String toString() {
			return "Albums [song=" + song + ", genre=" + genre + "]";
		}
	}
}

Output :

[Albums [song=Acquiesce, genre=Pop], Albums [song=Acadian Driftwood, genre=Roots], Albums [song=Above And Beyond, genre=Bluegrass], Albums [song=Abilene, genre=Bluegrass]]

Explanation :

In the above example, we have created a user defined class Albums, created a AlbumsComparator class and implemented Comparator interface.

In the compare method of AlbumsComparator class, to reverse the natural order changed from o1.song.compareTo(o2.song) to o2.song.compareTo(o1.song)

In the main class, created TreeSet class and passed AlbumsComparator as a comparator. Created four elements of Albums class and inserted into TreeSet and printed elements of set. if you see output songs got printed reverse to the natural order.

If you want to sort the order based on album genre, we can do that just by created new class with implementation Comparator and it will work as well but need to pass newly created class while creating TreeSet. FYR, as shown below.

static class AlbumsSongComparator implements Comparator<Albums>{
	//To specify order compare method is overriden
	@Override
	public int compare(TreeSetUserDefined.Albums o1, TreeSetUserDefined.Albums o2) {
	   //o2 object is compared with o1, it will reverse natural order
	   return o2.genre.compareTo(o1.genre);
	}			
}

Conclusion :

In this tutorial, we have covered what is TreeSet, its uses cases and working examples of it along with custom order using Comparator implementation.