值包含多个枚举值

时间:2012-08-17 04:48:55

标签: java enums

我有这个枚举:

public enum Direction {
    LEFT,
    RIGHT,
    ABOVE,
    BELOW
}

我是否可以获取并设置包含2个或更多值的Direction变量,例如:

Direction fromDirection = Direction.LEFT + Direction.ABOVE

如果有可能,请告诉我如何实现它。

5 个答案:

答案 0 :(得分:7)

您可以使用java.util.EnumSet

final Set<Direction> northEast = EnumSet<Direction>.of(Direction.NORTH, Direction.EAST);

当然,您可以使用任何其他集合实现,但EnumSet类型实现为位向量,非常节省空间和时间,并且可能是您目标的最佳内置工具。

您可能还想在枚举类型中定义静态方法,以检查有效组合。

答案 1 :(得分:3)

您也可以使用

private static EnumSet<Direction> someDirection = EnumSet.of(Direction.LEFT,Direction.RIGHT) ;

答案 2 :(得分:1)

你可以通过一些按位黑客实现这一目标。你无法获得比这更快的过程。在这种情况下,EnumSet速度较慢。

它基本上将枚举转换为数字,然后存储在单个整数中。 整数的每个字节表示枚举是打开还是关闭。但它有一个缺点,你不能使用大于32值的枚举。实际上,如果您使用值进行返工,则可以使用最多64个值枚举

这是一个巧妙的技巧,我用来将多个布尔数据存储到数据库中,其大小为单个整数。我可以用1列代表所有布尔值的总和来实现它,而不是每个代表一个布尔值的32列。唯一的缺陷就是你不能一眼就知道哪些布尔值是开/关的。

public enum ENUM
{
    AAA, SSS, DDD, FFF, GGG, HHH, JJJ, KKK, LLL, ZZZ, XXX, CCC;

    public static int add(int addTo, ENUM val)
    {
        return addTo | (1 << val.ordinal());
    }

    public static int remove(int removeFrom, ENUM val)
    {
        return removeFrom & ~(1 << val.ordinal());
    }

    public static boolean contains(int in, ENUM val)
    {
        return (in & (1 << val.ordinal())) != 0;
    }
}

public static void main(String[] args)
{
    int enums = 0;
    enums = ENUM.add(enums, ENUM.AAA);
    enums = ENUM.add(enums, ENUM.SSS);

    for (ENUM enu : ENUM.values())
        if (ENUM.contains(enums, enu))
            System.out.println(enu);
    System.out.println("Operation 2.");

    enums = ENUM.remove(enums, ENUM.AAA);
    enums = ENUM.remove(enums, ENUM.KKK);
    enums = ENUM.add(enums, ENUM.DDD);

    for (ENUM enu : ENUM.values())
        if (ENUM.contains(enums, enu))
            System.out.println(enu);
}

打印出以下结果:

AAA
SSS
Operation 2.
SSS
DDD

我会尽可能以最简单的方式解释这一点。

val.ordinal()是枚举的订单号。

1&lt;&lt; val.ordinal()向左移动X空格。 (因为1 = 00000000 00000000 00000000 00000001二进制,你最多可以移动31次)基本上,枚举顺序是整数中的位顺序。如果枚举的顺序是5,那么它将是1&lt;&lt; 5,whick意味着我们将二进制中的1向左移动5次。结果为00000000 00000000 00000000 00100000。

result = addTo | enumNum 这将检查枚举位的位置,并在结果整数中将其设置为1。因此,如果enumNum为00000000 00000000 00000000 00100000,结果(addTo)当前为00000000 00000000 00000000 00000001,则它将变为00000000 00000000 00000000 00100001。

result = removeFrom&amp; ~enumNum 首先,''反转位状态。 enumNum 00000000 00000000 00000000 00100000变为11111111 11111111 11111111 11011111.'&amp; '检查所有位并将它们设置为0,除非两个整数的当前位为1.所以让我们看看00000000 00000000 00000000 00100001&amp; ; 11111111 11111111 11111111 11011111变为00000000 00000000 00000000 00000001,因为唯一的1对是最合适的一对。

结果&amp; enumNum 如上所述,除非有一对1,否则所有位都会变为0。 00000000 00000000 00000000 00000001&amp; 00000000 00000000 00000000 00100000.此处没有1对,所以看起来结果是 = 0 。如果我们将当前结果设置为00000000 00000000 00000000 00100001那么我们&amp; 00000000 00000000 00000000 00100000我们将获得00000000 00000000 00000000 00100000作为最终结果。第5对是一对1,这就是它停留的原因。返回的数字是2 ^ 5 = 32,这是!= 0

有关按位操作如何工作的更多详细信息,请查看here

答案 3 :(得分:0)

否则您无法将值设置为枚举。它们是常量,每个常量都是Enum type的实例。

答案 4 :(得分:0)

  

我可以获取并设置包含2个或更多值的Direction变量

您已将Direction的类型声明为枚举,如果您尝试将其再次声明为某​​个变量,则会导致变量重定义错误。

Enums也是常量,你以后不能重置这些值。