Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Elegant generic "Cross product" of enums in java

I am searching for a way to build a wrapper for multiple enums. Say you have

public enum Enum1 {
    A,B,C
}

public enum Enum2 {
    ONE,TWO,THREE
}

I want to have a new enum with the literals

(A,ONE), (A,TWO), (A,THREE), (B,ONE), ...

The whole thing generic so that I don't have to know Enum1 and Enum2. Is there a way to build that or even extend it to n Enums?

Or should I look to other general ways to model that?

like image 800
ratatosk Avatar asked Oct 17 '25 10:10

ratatosk


1 Answers

I would set up a class to represent the tuple you are referring to. You could use generics here, if you want:

public class EnumTupleImpl<E1 extends Enum<E1>, E2 extends Enum<E2>> {
    private final E1 e1;
    private final E2 e2;

    public EnumTupleImpl(E1 e1, E2 e2) {
        this.e1 = e1;
        this.e2 = e2;
    }

    public E1 getE1() {
        return e1;
    }

    public E2 getE2() {
        return e2;
    }
}

Usage:

EnumTupleImpl<Enum1, Enum2> tupe1 = new EnumTupleImpl<Enum1, Enum2>(Enum1.A, Enum2.ONE);
EnumTupleImpl<Enum1, Enum2> tupe2 = new EnumTupleImpl<Enum1, Enum2>(Enum1.A, Enum2.TWO);
EnumTupleImpl<Enum1, Enum2> tupe3 = new EnumTupleImpl<Enum1, Enum2>(Enum1.A, Enum2.THREE);

You could also represent each tuple by a enum instance, like so:

public enum Tuple {
    AONE(Enum1.A, Enum2.ONE),
    ATWO(Enum1.A, Enum2.TWO),
    ATHREE(Enum1.A, Enum2.THREE);

    private Enum1 e1;
    private Enum2 e2;

    private EnumTupleEnum(Enum1 e1, Enum2 e2) {
        this.e1 = e1;
        this.e2 = e2;
    }

    public Enum1 getE1() {
        return e1;
    }

    public Enum2 getE2() {
        return e2;
    }
}

usage:

Tuple.AONE.getE1(); //returns A
Tuple.AONE.getE2(); //returns ONE

What may make sense for you would be to use a generic interface to wrap both the enum representation and class representation like so:

public interface EnumTuple<E1, E2> {
    E1 getE1();
    E2 getE2();
}

which would allow you to use the class or enum interchangeably:

public class EnumTupleImpl<E1 extends Enum<E1>, E2 extends Enum<E2>> imlements EnumTyple<E1, E2>{
...
}

public enum Tuple implements EnumTuple<Enum1, Enum2>{
...
}

usage:

EnumTuple<Enum1, Enum2> tupe1 = new EnumTupleImpl<Enum1, Enum2>(Enum1.A, Enum2.ONE);
EnumTuple<Enum1, Enum2> enum1 = Tuple.AONE;
like image 134
John Ericksen Avatar answered Oct 18 '25 23:10

John Ericksen