Here I have a solution in scala, which could be used from java, but can be - with much more code - been implemented in Java as well, to allow to use an iterator for the simplified for-loop:
for (List<Integer> list: permutations)
doSomething (list);

To allow for the simplified for-loop, we need to implement Iterable, which means we have to provide a method which returns an Iterator, which happens to be another interface, which means we have to implement 3 methods: hasNext (); next (); and remove ();
import java.util.*;
class PermutationIterator <T> implements Iterator <List <T>> {
private int current = 0;
private final List <T> lilio;
public final long last;
public PermutationIterator (final List <T> llo) {
lilio = llo;
long product = 1;
for (long p = 1; p <= llo.size (); ++p)
product *= p;
last = product;
}
public boolean hasNext () {
return current != last;
}
public List <T> next () {
++current;
return get (current - 1, lilio);
}
public void remove () {
++current;
}
private long fac (long l)
{
for (long i = l - 1L; i > 1L; --i)
l *= i;
return l;
}
/**
new version, which produces permutations in increasing order:
*/
private List <T> get (final long code, final List <T> list) {
if (list.isEmpty ())
return list;
else
{
int len = list.size (); // len = 4
long max = fac (len); // max = 24
long divisor = max / len; // divisor = 6
int i = (int) (code / divisor); // i = 2
List <T> second = new ArrayList <T> (list.size ());
second.addAll (list);
T el = second.remove (i);
List <T> tt = new ArrayList <T> ();
tt.add (el);
tt.addAll (get (code - divisor * i, second));
return tt;
}
}
public List <T> get (final int code)
{
return get (code, lilio);
}
}
class PermutationIterable <T> implements Iterable <List <T>> {
private List <T> lilio;
public PermutationIterable (List <T> llo) {
lilio = llo;
}
public Iterator <List <T>> iterator () {
return new PermutationIterator <T> (lilio);
}
private long invers (final List <T> pattern, final List <T> matcher)
{
if (pattern.isEmpty ())
return 0L;
T first = pattern.get (0);
int idx = matcher.indexOf (first);
long l = (pattern.size () - 1L) * idx;
pattern.remove (0);
matcher.remove (idx);
return l + invers (pattern, matcher);
}
/**
make a deep copy, since the called method will destroy the parameters
*/
public long invers (final List <T> lt)
{
List <T> copy = new ArrayList <T> (lilio.size ());
copy.addAll (lilio);
return invers (lt, copy);
}
}
class PermutationIteratorTest {
public static List <Integer> genList (int... a) {
List <Integer> li = new ArrayList <Integer> ();
for (int i: a)
li.add (i);
return li;
}
public static void main (String[] args) {
List <Integer> il = new ArrayList <Integer> ();
// autoboxing, add '0' to 'z' as Character:
for (int c = 0; c < 3; ++c)
{
il.add (c);
}
PermutationIterable <Integer> pi = new PermutationIterable <Integer> (il);
for (List<Integer> li: pi)
show (li);
System.out.println ("-again-");
// do it a second time:
for (List <Integer> li: pi)
show (li);
// test the inverse:
System.out.println ("for (2,1,0) expecting 5 ?= " + pi.invers (genList (2, 1, 0)));
System.out.println ("for (2,0,1) expecting 4 ?= " + pi.invers (genList (2, 0, 1)));
System.out.println ("for (1,0,2) expecting 3 ?= " + pi.invers (genList (1, 2, 0)));
System.out.println ("for (1,2,0) expecting 2 ?= " + pi.invers (genList (1, 0, 2)));
System.out.println ("for (0,2,1) expecting 1 ?= " + pi.invers (genList (0, 2, 1)));
System.out.println ("for (0,1,2) expecting 0 ?= " + pi.invers (genList (0, 1, 2)));
Random r = new Random ();
PermutationIterator <Integer> pitor = (PermutationIterator <Integer>) pi.iterator ();
for (int i = 0; i < 10; ++i)
{
int rnd = r.nextInt ((int) pitor.last);
List <Integer> rli = pitor.get (rnd);
show (rli);
}
}
public static void show (List <?> lo) {
System.out.print ("(");
for (Object o: lo)
System.out.print (o);
System.out.println (")");
}
}
PermutationIterator contains the additional, public method public List <T> get (final int code)
which is handy, if you like to pick a certain permutation by index, for example by random. You know the size (last) and can therefore take a permutation of the valid range by index.
PermutationIterable contains a method 'invers' which will generate the opposite: The index of a certain permutation.
Internally, invers and get work recursively, but all the permutations aren't produced recursively, so this shouldn't be a problem even for big permutations. Note, that for 21 elements, you exceed the size of longs, and 20 steps of recursion shouldn't be a problem at all.