7

有没有一种有效的方法可以找到 Java 中多个枚举之间的所有可能组合?

考虑以下三个枚举 -

public enum EnumOne {
   One ("One"),
   OneMore ("OneMore");
}

public enum EnumTwo {
   Two ("Two"),
}

public enum EnumThree {
   Three ("Three"),
   ThreeMore ("ThreeMore");
}

我希望输出在这些多个枚举之间产生所有可能的组合,即

{EnumOne.One, EnumTwo.Two, EnumThree.Three},
{EnumOne.One, EnumTwo.Two, EnumThree.ThreeMore},
{EnumOne.OneMore, EnumTwo.Two, EnumThree.Three},
{EnumOne.OneMore, EnumTwo.Two, EnumThree.ThreeMore}

希望能找到有效的处理方法。

谢谢

4

3 回答 3

1

算法的复杂性是 O(NxMxK .... xZ)如果我错了,我不知道这是否是一种“有效的方式” ....我用作回溯解决方案

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

public class ProductEnums {

    public enum EnumOne {
        One,
        OneMore;
    }

    public enum EnumTwo {
        Two,
    }

    public enum EnumThree {
        Three,
        ThreeMore;
    }

    public static void main(String[] args) {
        // pass each values in enums
        List a = product(EnumOne.values(),
                EnumTwo.values(), EnumThree.values());
        System.out.println(a);
    }

    public static List<List<Enum>> product(Enum[]... enums) {
        return product(new ArrayList<>(Arrays.asList(enums)));
    }

    public static List<List<Enum>> product(List<Enum[]> enums) {
        if (enums.isEmpty()) {
            //Trivial case of recursive function
            return new ArrayList<>();
        }
        //remove first element
        Enum[] myEnums = enums.remove(0);
        List<List<Enum>> out = new ArrayList<>();
        for (Enum e : myEnums) {
            //call recursive
            List<List<Enum>> list = product(enums);
            for (List<Enum> list_enum : list) {
                //for each list get from recursion adding element e
                list_enum.add(0, e);
                out.add(list_enum);
            }
            if(list.isEmpty()){
                List<Enum> list_enum = new ArrayList<>();
                list_enum.add(e);
                out.add(list_enum);
            }
        }
        enums.add(0, myEnums); //Backtraking
        return out;
    }
}

结果

[[一、二、三]、[一、二、三更]、[一更、二、三]、[一、二、三更]]

于 2015-05-01T20:56:42.500 回答
0

这是一个基于迭代器的解决方案。这样,如果它在许多带有大量枚举常量的枚举类型上运行,内存消耗就不会爆炸。因此执行效率应该很好(此外,实现避免了递归)。

import java.util.Iterator;
import java.util.List;
import java.util.NoSuchElementException;

public class EnumCombination implements Iterable<Enum<?>[]> {

    private final Enum<?>[][] enumConstants;
    private final int[] limits;
    private final boolean emptyCombination;

    public EnumCombination(final List<Class<? extends Enum<?>>> enums) {
        this.limits = new int[enums.size()];
        this.enumConstants = new Enum<?>[enums.size()][];

        boolean empty = enums.isEmpty();
        for (int i = 0; i < enums.size(); i++) {
            final Enum<?>[] enumElements = enums.get(i).getEnumConstants();
            enumConstants[i] = enumElements;
            limits[i] = enumElements.length - 1;
            empty |= enumElements.length == 0;
        }
        this.emptyCombination = empty;
    }

    @Override
    public Iterator<Enum<?>[]> iterator() {
        return new EnumCombinationIterator();
    }

    private class EnumCombinationIterator implements Iterator<Enum<?>[]> {
        private final int[] cursors = new int[limits.length];
        private boolean exhausted = emptyCombination;

        @Override
        public boolean hasNext() {
            return !exhausted;
        }

        @Override
        public Enum<?>[] next() {
            if (exhausted)
                throw new NoSuchElementException();

            final Enum<?>[] result = new Enum<?>[cursors.length];
            for (int i = 0; i < cursors.length; i++) {
                result[i] = enumConstants[i][cursors[i]];
            }
            moveCursors();

            return result;
        }

        private void moveCursors() {
            for (int i = cursors.length - 1; i >= 0; i--) {
                cursors[i] = cursors[i] == limits[i] ? 0 : cursors[i] + 1;
                if (cursors[i] != 0) {
                    break;
                } else if (i == 0) {
                    exhausted = true;
                }
            }
        }
    }
}

EnumCombination可以这样使用:

import java.util.*;

public class Main {

    public enum EnumOne {
        One,
        OneMore
    }

    public enum EnumTwo {
        Two
    }

    public enum EnumThree {
        Three,
        ThreeMore
    }

    public static void main(String... args) {
        EnumCombination enumCombination = new EnumCombination(
                Arrays.asList(EnumOne.class, EnumTwo.class, EnumThree.class));

        for (final Enum<?>[] ec : enumCombination) {
            System.out.println(Arrays.toString(ec));
        }
    }
}

但是,当然,也可以使用番石榴cartesianProduct()……</p>

于 2016-05-23T12:57:19.980 回答
-1

这样的事情怎么样。

void printAll(List<Class> enums, int i, String[] msg) {
    if (!enums.get(i).isEnum()) {
        throw new IllegalStateException();
    }
    Object[] enumsConstants = enums.get(i).getEnumConstants();
    if (i == 0) {
        //first iteration
        for (Object o : enumsConstants) {
            if (enums.size() == 1) {
                System.out.println("{ " + o.toString() + " }");
            } else {
                msg = new String[enums.size()];
                msg[0] = "{ " + o.toString();
                printAll(enums, i + 1, msg);
            }
        }
    } else if (i == enums.size() - 1) {
        //on the last iteration
        for (Object o : enumsConstants) {
            msg[i] = ", " + o.toString() + " }";
            System.out.println(Arrays.toString(msg));
        }
    } else {
        //middle iteration
        for (Object o : enumsConstants) {
            msg[i] = ", " + o.toString();
            printAll(enums, i + 1, msg);
        }
    }
}

你会像这样使用它

printAll(allMyEnumClassesList, 0, null);
于 2015-05-01T20:10:32.537 回答