私はこの列挙型を持っています:
public enum Direction {
LEFT,
RIGHT,
ABOVE,
BELOW
}
2 つ以上の値を含む変数を取得および設定できますかDirection
。たとえば、次のようになります。
Direction fromDirection = Direction.LEFT + Direction.ABOVE
可能であれば、それを達成する方法を教えてください。
を使用できますjava.util.EnumSet
:
final Set<Direction> northEast = EnumSet<Direction>.of(Direction.NORTH, Direction.EAST);
もちろん、他のセットの実装を使用することもできますが、EnumSet
型はビット ベクトルとして実装され、スペースと時間の効率が非常に高く、おそらく目標に最適な組み込み機能です。
有効な組み合わせをチェックする列挙型で静的メソッドを定義することもできます。
使用することもできます
private static EnumSet<Direction> someDirection = EnumSet.of(Direction.LEFT,Direction.RIGHT) ;
ビットごとのハッキングでそれを実現できます。これより速いプロセスはありません。この場合、EnumSet は遅くなります。
基本的に、列挙型を数値に変換し、単一の整数に格納します。整数の各バイトは、列挙型がオンかオフかを表します。ただし、これには 1 つの欠点があります。32 値を超える列挙型を操作できないことです。実際には、長い値で動作するように作り直すと、最大 64 個の値の列挙型を使用できるようになります。
これは、単一の整数のサイズで複数のブール値データをデータベースに格納するために使用する巧妙なトリックです。それぞれが単一のブール値を表す 32 列を作成する代わりに、すべてのブール値の合計を表す 1 つの列でそれを実現できます。これの唯一の欠点は、一目でどのブール値がオン/オフされているかを知ることができないことです。
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 << val.ordinal()は、X スペースのビットを左に移動します。(1 = 00000000 00000000 00000000 00000001 なので、最大 31 回移動できます) 基本的に列挙順は整数のビット順です。列挙型の順序が 5 の場合、1 << 5 になります。これは、バイナリの 1 を左に 5 回移動することを意味します。結果は 00000000 00000000 00000000 00100000 になります。
結果 =追加先 | enumNumこれは enum ビットの位置をチェックし、結果の整数でそれを 1 に設定します。たとえば、enumNum が 00000000 00000000 00000000 00100000 で、結果 (addTo) が現在 00000000 00000000 00000000 00000001 の場合、00000000 00000000 00000000 0010 になります。
result = removeFrom & ~enumNumまず、' ~ ' はビットの状態を反転します。Enumnum 00000000000000000000000000000000000000000は11111111111111111111111111111111になります。 00000001 は、1 の唯一のペアが最も右のペアであるためです。
result & enumNum上で述べたように、1 のペアがない限り、すべてのビットが 0 になります。ここには 1 のペアがないため、結果は=0のように見えます。現在の結果を 00000000 00000000 00000000 00100001 に設定すると、00000000 00000000 00000000 00100000 と 00000000 00000000 00000000 00100000 が最終結果として得られます。5 番目のビット ペアは 1 のペアであるため、そのまま残ります。返される数値は 2^5=32 で、これは!= 0です。
ビット演算の仕組みの詳細については、こちらをご覧ください
いいえ、列挙型に値を設定することはできません。それらは定数であり、すべての定数はEnum 型のインスタンスです。
2 つ以上の値を含む方向変数を取得および設定できますか
の型はすでにDirection
列挙型として宣言されています。変数として再度宣言しようとすると、変数の再定義エラーが発生します。
また、列挙型は定数であり、後で値をリセットすることはできません。