Getting permutations of a set
There's a number of things going on here, but the first thing that comes to mind is that you're placing an object on the heap that you simply discard (the entire class) for no apparent reason (speaking logically, not in terms of objects created).  Given that you don't appear to keep the object at all, this is unnecessary - do this all with static methods.  Additionally, this is not threadsafe, and the basic design cannot be adjusted to execute on multiple threads.  Furthermore, you're returning a Set&lt;List&lt;E&gt;&gt;, but your results are logically Set&lt;Set&lt;E&gt;&gt; (because you don't have repeats) - You probably ought to either adjust your results, or change your return results.

There's also a compile error in your code since you switched to the generics version, because of type inference (and this took me a while to figure out).

Most of the disconnect is occurring because of the odd blend of static and instance methods.  Additionally, you're attempting to use a builder pattern for something that doesn't really call for it - as near as the caller of your method knows, your SetPermutations class is never instantiated (which is false).  Also, you add object to permutationSet... and then almost immediately remove it.  Regardless of the performance implications of that, it's a terrible thing to do to a developer's mind.



Here's my (intial) take on the issue.  Note that this version is threadsafe (so long as T is an immutable object), and amenable to (easier) threading.  There are a few areas that could maybe be tweaked, especially as I'm creating a few more objects than I actually need (notably, my termination condition in permute), but this should be a better starting place.

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;


public abstract class SetPermutations { 

    private SetPermutations() {
        // no state.
    }

    public static &lt;T&gt; Set&lt;Set&lt;T&gt;&gt; getSetPermutations(final Collection&lt;? extends Collection&lt;T&gt;&gt; input) {
        if (input == null) {
            throw new IllegalArgumentException("Input not provided!");
        }
        final List&lt;Set&lt;T&gt;&gt; saved = new ArrayList&lt;Set&lt;T&gt;&gt;();
        for (Collection&lt;T&gt; c : input) {
            Set&lt;T&gt; s = new HashSet&lt;T&gt;(c);
            c.remove(null);
            if (c.size() &gt;= 1) {
                saved.add(s);
            } else {
                throw new IllegalArgumentException("Input includes null/empty collection!");
            }
        }

        return permute(new HashSet&lt;T&gt;(), saved);
    } 

    private static &lt;T&gt; Set&lt;Set&lt;T&gt;&gt; permute(final Set&lt;T&gt; initial, final List&lt;Set&lt;T&gt;&gt; itemSets) {

        if (itemSets.isEmpty()) {
            return Collections.singleton(initial);
        }

        final Set&lt;T&gt; items = itemSets.get(0);
        final List&lt;Set&lt;T&gt;&gt; remaining = itemSets.subList(1, itemSets.size());
      final int computedSetSize = initial.size() * items.size() * remaining.size();
        final Set&lt;Set&lt;T&gt;&gt; computed = new HashSet&lt;Set&lt;T&gt;&gt;(computedSetSize, 1);

        for (T item : items) {
            if (!initial.contains(item)) {
                Set&lt;T&gt; permutation = new HashSet&lt;T&gt;(initial);
                permutation.add(item);
                computed.addAll(permute(permutation, remaining));
            }
        }

        return computed;
    }

} 


And here's the (revised) JUnit test to prove behaviour:

@Test 
public void setPermutationsTest() { 
    List&lt;List&lt;String&gt;&gt; data = new ArrayList&lt;List&lt;String&gt;&gt;();
    data.add(Arrays.asList("A", "B"));
    data.add(Arrays.asList("A","B","C","D"));
    data.add(Arrays.asList("D","E"));
    Set&lt;Set&lt;String&gt;&gt; expected = new HashSet&lt;Set&lt;String&gt;&gt;();
    expected.add(new HashSet&lt;String&gt;(Arrays.asList("A", "B", "D")));
    expected.add(new HashSet&lt;String&gt;(Arrays.asList("A", "B", "E")));
    expected.add(new HashSet&lt;String&gt;(Arrays.asList("A", "C", "D")));
    expected.add(new HashSet&lt;String&gt;(Arrays.asList("A", "C", "E")));
    expected.add(new HashSet&lt;String&gt;(Arrays.asList("A", "D", "E")));
    expected.add(new HashSet&lt;String&gt;(Arrays.asList("B", "C", "D")));
    expected.add(new HashSet&lt;String&gt;(Arrays.asList("B", "C", "E")));
    expected.add(new HashSet&lt;String&gt;(Arrays.asList("B", "D", "E")));
    Set&lt;Set&lt;String&gt;&gt; result = SetPermutations.&lt;String&gt;getSetPermutations(data); 
    assertTrue(result.containsAll(expected)); 
    assertTrue(result.size() == expected.size()); 
} 


(I removed "F" from the last collection, as it wasn't adding anything in terms of conditions - it fufilled the same function as "E").



EDIT:  

The main reason why this is (more, and as much as can be reasonably coded for) threadsafe is the fact that you're not (completely) operating on a 'saved' copy:


You save off maxDepth before copying the 'exterior' collection.  If the size of that collection changes, maxDepth's value is now incorrect (results undefined).
You copy (and work from) the 'exterior' collection, but don't copy the 'interior' collections (The copy constructors might be deep for existing collections, but I doubt it, and won't be for custom collections).  This means that if any of the interior collections are modified during process run, you won't get correct results.


As for the static method instantiating a version of itself - there's no problem with that.  In fact, that generally forms the basis of a Factory Pattern.  The catch is that the instantiation is being returned - that is, the desired result is the instantiation.  Here, the only result is that you end up with a confusing use of instance variables.  The permutationSet methods end up being unwanted noise (It would have been better to explicitly just use the constructors), and are misleading to boot (you're returning a LIST).  Additionally, because of the use of the instance variables, it becomes non-trivial to reason about the state of the various collections.  NONE of the work done by instance methods benefits significantly from working on instance variables.  The only (theorhetical) benefit gained is that you work with a single copy of a result HashSet (because I define intermediate ones) - however, if it's an issue, the necessary collection should be passed in (as in a load() method.
Also, by permorming the instantiation as you have, you've completely eliminated any potential hope of threading the process (a potential concern, given that this is basically an O(n ^ m) process, where n is the number of collections, and m is the size of the collections, assuming roughly equal collection sizes).  With a thread pool and using futures, a non-instantiated version (or at least, not instantiated like this) can be threaded fairly trivially.