TreeSet in Java

A NavigableSet implementation based on a TreeMap.
The elements are ordered using their natural ordering, or by a Comparator provided at set creation time, depending on which constructor is used.
Like HashSet, TreeSet also implements Set interface.
Like HashSet, TreeSet allows to store only unique elements in their objects.HashSet is much faster than TreeSet because HashSet has constant-time, whereas TreeSet has log-time for most operations like add, remove and contains.
Unlike HashSet, TreeSet offers a few handy methods to deal with the ordered set like first(), last(), headSet(), and tailSet() etc.
If you need to maintain insertion order (not sorting order) then you may use LinkedHashSet, that is implemented as a hash table with a linked list running through it.

Like HashSet, HashMap, LinkedHashMap and TreeMap, the TreeSet implementation is not synchronized. So multiple threads access a tree set concurrently, and at least one of the threads modifies the set structurally, it must be synchronized externally. This is typically accomplished by synchronizing on some object that naturally encapsulates the set. If no such object exists, the set should be “wrapped” using the Collections.synchronizedSortedSet method. This is best done at creation time, to prevent accidental unsynchronized access to the set:

SortedSet s = Collections.synchronizedSortedSet(new TreeSet(...));

TreeSet is Fail-fast

If the set is structurally modified at any time after the iterator is created, in any way except through the iterator’s own remove method, the iterator will throw a ConcurrentModificationException. Thus, in the face of concurrent modification, the iterator fails quickly and cleanly, rather than risking arbitrary, non-deterministic behavior at an undetermined time in the future.

The fail-fast behavior of an iterator cannot be guaranteed and iterators throw ConcurrentModificationException on a best-effort basis. Therefore, it would be wrong to write a program that depended on this exception for its correctness: the fail-fast behavior of iterators should be used only to detect bugs.