An iterator returning all possible permutations of a list in Java
Your solution looks good. It's a really challenging task. This is because you have to "flatten" an algorithm with recursive nature. Furthermore you have to break it apart into single steps and to be able to resume at the last step made.

So there are little things that I would change:


I like separated classes instead of inner classes they are more handy in testing
I would have separated the algorithm in "generateNextPermutation()" in an additional class.
I would follow the recursive nature of the problem and build a recursive structure. This is a slightly different approach.
I do not exactly know how the algorithm should behave if you provide an empty list. I assume that you will have one permutation as result. So I adapted your algorithm to work with an empty array of indices.


You see that our solutions do not differ in structure. Only the algorithm to generate a new permutation is extracted in a class and reformulated.

I unpacked this riddle (I somehow liked this riddle) and I want to provide a solution that can use either your algorithm or mine. But finally they converged against the same interface. I expected that as I know there is only one structure that fits the problem best. We may not have found it but both solutions have a "meeting" where the structure is mostly the same AND the things that may be different can work under the same abstraction. Sure, most structure was provided by the interfaces "Iterable" and "Iterator" but I found it interesting how the algorithms are interchangeable.

So first of all the interface for our algorithms:

public interface PermutationResolver&lt;T&gt; {

    List&lt;T&gt; resolvePermutation(List&lt;T&gt; base);

    boolean nextStep();

}


Your algorithm:

public class IndicesWalker&lt;T&gt; implements PermutationResolver&lt;T&gt; {

    private int[] indices;

    public IndicesWalker(int elements) {
        indices = new int[elements];
        for (int i = 0; i &lt; indices.length; ++i) {
            indices[i] = i;
        }
    }

    @Override
    public boolean nextStep() {

        if (indices.length == 0) return false;

        int i = indices.length - 2;

        while (i &gt;= 0 &amp;&amp; indices[i] &gt; indices[i + 1]) {
            --i;
        }

        if (i == -1) {
            // No more new permutations.
            return false;
        }

        int j = i + 1;
        int min = indices[j];
        int minIndex = j;

        while (j &lt; indices.length) {
            if (indices[i] &lt; indices[j] &amp;&amp; indices[j] &lt; min) {
                min = indices[j];
                minIndex = j;
            }

            ++j;
        }

        swap(indices, i, minIndex);

        ++i;
        j = indices.length - 1;

        while (i &lt; j) {
            swap(indices, i++, j--);
        }
        return true;
    }

    @Override
    public List&lt;T&gt; resolvePermutation(List&lt;T&gt; base) {

        List&lt;T&gt; newPermutation = new ArrayList&lt;&gt;(indices.length);

        for (int i : indices) {
            newPermutation.add(base.get(i));
        }

        return newPermutation;
    }

    private void swap(int[] array, int a, int b) {
        int tmp = array[a];
        array[a] = array[b];
        array[b] = tmp;
    }

}


Mine:

public class RecursiveCounter&lt;T&gt; implements PermutationResolver&lt;T&gt; {

    private int i;
    private int max;
    private RecursiveCounter&lt;T&gt; nextState;

    public RecursiveCounter(int max) {
        this.max = max;
        this.i = 0;
        if (this.max &gt; 1) {
            nextState = new RecursiveCounter&lt;T&gt;(max - 1);
        }
    }

    @Override
    public boolean nextStep() {

        boolean wasIncremented = true;

        if (nextState != null) {
            if (!nextState.nextStep()) {
                if (this.i == this.max - 1) {
                    this.i = 0;
                    wasIncremented = false;
                } else {
                    i++;
                }
            }
        } else {
            wasIncremented = false;
        }

        return wasIncremented;
    }


    private int getI(int level) {
        if (level == 0) {
            return this.i;
        } else {
            return nextState.getI(level - 1);
        }
    }

    @Override
    public List&lt;T&gt; resolvePermutation(List&lt;T&gt; base) {
        List&lt;T&gt; result = new ArrayList&lt;&gt;();
        List&lt;T&gt; work = new ArrayList&lt;&gt;(base);
        for(int i = 0; i &lt; base.size(); i++) {
            result.add(work.remove(getI(i)));
        }
        return result;
    }


}


The iterator:

public class PermutationIterator&lt;T&gt; implements Iterator&lt;List&lt;T&gt;&gt;  {

    private List&lt;T&gt; base;

    private PermutationResolver&lt;T&gt; permutationResolver;
    private List&lt;T&gt; next;

    public PermutationIterator(List&lt;T&gt; base, PermutationResolver&lt;T&gt; resolver) {
        this.base = base;
        this.next = new ArrayList&lt;&gt;(base);
        this.permutationResolver = resolver;
    }

    private List&lt;T&gt; generateNextPermutation(boolean isLast) {

        List&lt;T&gt; result = null;

        if (!isLast) {
            result = getPermutationResolver().resolvePermutation(base);
        }

        return result;
    }

    @Override
    public boolean hasNext() {
        return next != null;
    }

    @Override
    public List&lt;T&gt; next() {

        if (!hasNext()) {
            throw new NoSuchElementException();
        }

        List&lt;T&gt; current = next;

        this.next = generateNextPermutation(!getPermutationResolver().nextStep());

        return current;
    }


    private PermutationResolver&lt;T&gt; getPermutationResolver() {
        return permutationResolver;
    }

}


The iterable:

public class PermutationIterable&lt;T&gt; implements Iterable&lt;List&lt;T&gt;&gt; {

    private List&lt;T&gt; base;
    private PermutationResolver&lt;T&gt; resolver;

    public PermutationIterable(List&lt;T&gt; base, PermutationResolver&lt;T&gt; resolver) {
        super();
        this.base = base;
        this.resolver = resolver;
    }

    @Override
    public Iterator&lt;List&lt;T&gt;&gt; iterator() {
        return new PermutationIterator&lt;T&gt;(base, resolver);
    }

}


Code in action with both algorithms:

public class Main {

    public static void main(String[] args) {

        List&lt;String&gt; base = Arrays.asList();

        PermutationIterable&lt;String&gt; permutationIterable1 = new PermutationIterable&lt;String&gt;(base, new IndicesWalker&lt;String&gt;(base.size()));

        for (List&lt;String&gt; permutation : permutationIterable1) {
            System.out.println(permutation);
        }

        PermutationIterable&lt;String&gt; permutationIterable2 = new PermutationIterable&lt;String&gt;(base, new RecursiveCounter&lt;String&gt;(base.size()));

        for (List&lt;String&gt; permutation : permutationIterable2) {
            System.out.println(permutation);
        }

    }

}