Table of Contents
Overview
The Set interface has no definition of first or last elements. To say differently, there is no order in a Set. SortedSet solves that problem by offering an order of elements and letting you access elements by their indexes.
Let’s take a look at the part of the Set interface where we have the SortedSet:
As you can see, SortedSet has no direct concrete implementation. We have TreeSet
and ConcurrentSkipListSet
implement SortedSet
through NavigableSet
interface.
Here are the methods of SortedSet
Method name | Function |
comparator() | Returns the comparator that used to order elements in the set |
first() | Get the first element |
headSet(E e) | Get a SortedSet of elements that are less than e |
last() | Get the last element |
tailSet(E from) | Get a SortedSet of elements that are greater than or equal to e (inclusive) |
subSet(E from, E to) | Get a subset of elements that are greater than from and less than to |
spliterator() | Creates a Spliterator over the elements in the set |
Since elements in SortedSet
are ordered, the elements’ class must implement Comparable or when creating the SortedSet
, you must pass in a Comparator that accepts the element’s type.
You may recall another data structure that has similar requirements, which is PriorityQueue
.
SortedSet in action
Let’s try the operations of a SortedSet by using a TreeSet. As you can see from the diagram, TreeSet
implements NavigableSet
that in turn extends SortedSet
.
Consider the following block:
private static void sortedSetBasicOperations() { SortedSet<String> mySet = new TreeSet<>(); mySet.add("Karen"); mySet.add("Zed"); mySet.add("Abby"); mySet.add("Quentin"); mySet.add("Randall"); //print the full set System.out.println("The full set is: " + mySet); //Getting first and last elements System.out.println("First element: " + mySet.first()); System.out.println("Last element: " + mySet.last()); //Getting all elements from Karen System.out.println("From Karen: " + mySet.tailSet("Karen")); //Getting all elements before Quentin System.out.println("To Quentin: " + mySet.headSet("Quentin")); //Getting all elements from Karen to before Quentin System.out.println("From Karen To Quentin: " + mySet.subSet("Karen", "Quentin")); }
This is the output of the above code when executed:
Using SortedSet in multi-threaded code
From the diagram, you can see, that there is one implementation of the SortedSet
in the java.util.concurrent
package. That’s ConcurrentSkipListSet
.
Let’s first consider an example where we use non-safe SortedSet
first then we’ll use ConcurrentSkipListSet
to address the issue.
private static void nonSafeTreeSetOperation() throws InterruptedException { var numberSet = new TreeSet<Integer>(); ExecutorService service = Executors.newFixedThreadPool(10); for (int i = 0; i < 20; i++) { int finalI = i; service.submit(() -> numberSet.add(finalI) ); } service.shutdown(); service.awaitTermination(10, TimeUnit.SECONDS); System.out.println("The set size: " + numberSet.size()); System.out.println("The set: " + numberSet); }
When executing this code, you might see different results between executions:
Here are some possible outcomes:
Now, if we change TreeSet
to ConcurrentSkipListSet
, the problem is solved:
private static void safeTreeSetOperation() throws InterruptedException { var numberSet = new ConcurrentSkipListSet<Integer>(); ExecutorService service = Executors.newFixedThreadPool(10); for (int i = 0; i < 20; i++) { int finalI = i; service.submit(() -> numberSet.add(finalI) ); } service.shutdown(); service.awaitTermination(10, TimeUnit.SECONDS); System.out.println("The set size: " + numberSet.size()); System.out.println("The set: " + numberSet); }
The output is consistent. There are always 20 elements in the list:
Conclusion
As you can see, the SortedSet
data structure adds more power to the Set
interface. There is no order in a set. However, with SortedSet
, you can have the items ordered in their natural order or you can specify a comparator to offer the order mechanism yourself.
You can find the code of this article here on Github.
I build softwares that solve problems. I also love writing/documenting things I learn/want to learn.