Skip to content

Split a list into n sublists in all possible ways

I want to split a list into a given number n sublists in all possible ways in Java.

For example [1, 2, 3, 4] where n = 3 would include the following lists (but would not be a complete solution – complete would require much more space):

([], [], [1,2,3,4])
([1],[2,3,4], [])


I adapted a solution from another similar question (Split a list into two sublists in all possible ways) however it only works for creating lists of 2 sublists and I am struggling to grasp how to implement it for a flexible rather than hardcoded number of sublists.

Here is my code:

public List<List<EGroup>> permutation(List<E> list) {
        List<List<E>> sublists = new ArrayList<List<E>>();
        for (int i = 0; i <= list.size(); i++) {
          permutationSplit(list, sublists, i, new ArrayList<E>(), 0);

        List<List<EGroup>> listOfEGroupPairs = new ArrayList<List<EGroup>>();
        for (List<E> subList : sublists) {
            List<E> listCopy = new ArrayList<E>(list);
            EGroup e1 = new EGroup(subList);
            EGroup e2 = new EGroup(listCopy);   
            List<EGroup> egr = new ArrayList<EGroup>();
        return listOfEGroupPairs;

    public void permutationSplit(List<E> list, List<List<E>> subLists, int sublistSize, List<E> currentSubList,
          int startIndex) {
        if (sublistSize == 0) {
        } else {
          for (int i = startIndex; i < list.size(); i++) {
            List<E> newSubList = new ArrayList<E>(currentSubList);
            permutationSplit(list, subLists, sublistSize, newSubList, i + 1);

I need to create n number of EGroup objects to add to listOfEGroupPairs rather than the hardcoded 2, but how to always get the right number (n) of sublists of varied size each loop?



If I understand the question correctly, each element of the original list can end up in any of the n sublists. That means, there are n^s possible sublists (s being the number of elements in the original list), which can be enumerated in a simple loop. With a bit of modulo and integer division you can then get the proper “bucket” for each element and prepare the results accordingly.

public <T> List<List<List<T>>> partition(List<T> lst, int n) {
    var result = new ArrayList<List<List<T>>>();
    // k = SUM ( pos of lst[i] * n^i ) 
    for (int k = 0; k < Math.pow(n, lst.size()); k++) {
        // initialize result
        List<List<T>> res = IntStream.range(0, n)
                .mapToObj(i -> new ArrayList<T>())
        // distribute elements to sub-lists
        int k2 = k;
        for (int i = 0; i < lst.size(); i++) {
            res.get(k2 % n).add(lst.get(i));
            k2 /= n;
    return result;