Q:

Java: Sorting TreeSets based on size

I am looking for a way to sort a set of sets - more specifically, the data structure is required to have the following properties:

Both the "outer" and the "inner" collection should be sets, i.e. there should be no duplicate elements within contained sets and no duplicate sets.
The set should be sorted according to the length of the contained sets in ascending order, i.e. {{A}, {A, B}, {A, C, F}, {B, D, F}} is valid whereas {{A, C, F}, {A, B}, {B, D, F}, {A}} is not.
It should be possible to iterate over individual contained sets as well as over all sets. Naturally, iterating over all sets should list them in ascending order based on their respective sizes.
If two sets have the same size, the order may be arbitrary.

My basic approach is a TreeSet<TreeSet<T>>, although since the contained TreeSets need to be sorted in a custom behaviour, I have written a wrapper class (unnecessary details omitted, such as additional constructors and methods):
import java.util.TreeSet;
import java.util.Iterator;
import java.util.Collection;

public class WrappedSet< T > implements Comparable< WrappedSet< T >>, Iterable< T >  {
    protected TreeSet< T > set;

    public WrappedSet( Collection< T > collection ) {
        set = new TreeSet< T >( collection );
    }

    public int size() {
        return set.size();
    }

    @Override
    public Iterator< T > iterator() {
        return set.iterator();
    }

    @Override
    public int compareTo( WrappedSet< T > other ) {
        if ( set.equals( other.set )) {
            return 0;
        }
        else {
            return ( set.size() >= other.set.size()) ? 1 : -1;
        }
    }

    @Override
    public String toString() {
        return set.toString();
    }
}

For the purpose of showing the problem, I am using this main function:
public static void main( String[] args ) {
    TreeSet< WrappedSet< String >> wsets = new TreeSet< WrappedSet< String >>();

    for ( String arg : args ) {
        wsets.add( new WrappedSet< String >( new TreeSet< String >( Arrays.asList( arg.split( "," )))));
    }

    System.out.println( "Input sets: " + Arrays.toString( wsets.toArray()));
}

I understand that if my .equals() for this class was based on testing the individual sets for equality, my "class [would have] a natural ordering that is inconsistent with equals", as the CompareTo documentation phrases it. I also understand that this is probably the reason why the output is (sometimes) incorrect. Consider the following example:
Input (command line): A,B,E A,C,F B,D,F A A,B,E
Output: Input sets: [[A], [A, B, E], [A, C, F], [B, D, F], [A, B, E]]
As you can see, {A, B, E} comes up twice, and I suppose this is because the TreeSet traverses the tree in order to find an existing entry with this value, but ends up not finding it because the order of the elements is independent of their actual values - only their sizes.
How could I achieve the desired behaviour in a consistent way? Please note that this is not homework. Solutions not based on TreeSets are therefore naturally welcome.

A:

For your outer TreeSet to accept two different sets of the same size as different elements, you need to decide a sorting order of them even when you don’t care about their order. Otherwise your set will not work as you expected.
Rather then a wrapper class for the inner TreeSets I think I’d prefer just to write a comparator. But make sure your comparator defines a total ordering on the inner sets and only declares two sets equal of they are indeed equal also in the sense that only one of them should be in the set. And as RealSkeptic and others have said in comments, in order to fulfil the Comparator contract, you need to fulfil:

The implementor must ensure that sgn(compare(x, y)) ==
  -sgn(compare(y, x)) for all x and y.

(from the documentation)
Here’s just a very rough example of a Comparator that does compare more than just the size when the size is the same. It’s not hard to devise an example where it still doesn’t do well enough, but I will leave it to you to write the right comparator for your situation.
    Comparator<TreeSet<?>> compareBySize 
            = Comparator.comparing((TreeSet<?> s) -> s.size())
                    .thenComparing(TreeSet::toString);

    TreeSet<TreeSet<Character>> mySet = new TreeSet<>(compareBySize);
    mySet.addAll(Arrays.asList(
                new TreeSet<>(Arrays.asList('A', 'B', 'E')),
                new TreeSet<>(Arrays.asList('A', 'C', 'F')),
                new TreeSet<>(Arrays.asList('B', 'D', 'F')),
                new TreeSet<>(Arrays.asList('A')),
                new TreeSet<>(Arrays.asList('A', 'B', 'E'))
            ));
    System.out.println(mySet);

This prints
[[A], [A, B, E], [A, C, F], [B, D, F]]

I believe this is correct.
As an aside, it is generally recommended to program towards interfaces rather than implementations. If you want to do this, depending on your further requirements, either use the SortedSet or the NavigableSet interface. You need two changes: First, the comparator should be (using SortedSet in my example):
    Comparator<SortedSet<?>> compareBySize 
            = Comparator.comparing((SortedSet<?> s) -> s.size())
                    .thenComparing(SortedSet::toString);

Second declare your set as SortedSet<SortedSet<Character>> mySet, but still use new TreeSet<>(…) in the instantiations.

