我有这个枚举:
public enum Direction {
LEFT,
RIGHT,
ABOVE,
BELOW
}
我是否可以获取并设置包含2个或更多值的Direction
变量,例如:
Direction fromDirection = Direction.LEFT + Direction.ABOVE
如果有可能,请告诉我如何实现它。
答案 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也是常量,你以后不能重置这些值。