web-dev-qa-db-ja.com

EnumSetとはどういう意味ですか?

私は次の例を持っています:

import Java.util.EnumSet;
import Java.util.Iterator;

public class SizeSet {

    public static void main(String[] args) {
        EnumSet largeSize = EnumSet.of(Size.XL,Size.XXL,Size.XXXL);
        for(Iterator it = largeSize.iterator();it.hasNext();){
            Size size = (Size)it.next();
            System.out.println(size);
        }
    }
}


enum Size {
  S, M, L, XL, XXL, XXXL;

}

このコードでは、EnumがSizesのEnumタイプを作成することを理解できます。

私の質問は:largeSizeはEnumSet型のオブジェクトですか?それは本当にどういう意味ですか?もっとよく理解したいです。

64
Adam

変数については、その型は宣言で見つかります。

EnumSet largeSize

はい、largeSize(コレクションなのでlargeSizesという名前にする必要があります)はEnumSet型です。また、生成される必要があるため、次のように宣言する必要があります。

EnumSet<Size> largeSizes

つまり、largeSizesEnumSet型です。 EnumSetは、特定の列挙型の列挙インスタンスを含むSetであり、他のSet実装(HashSetTreeSetなど、より効率的な方法で等。)。 EnumSetが何であるかを知るには、その [〜#〜] api [〜#〜] を読んでください。

42
JB Nizet

コードを簡素化する

EnumSet<Size> largeSize = EnumSet.of(Size.XXXL, Size.XXL, Size.XL, Size.L);
for(Size size: largeSize)
    System.out.print(size+" ");

LargeSizeは、Enumを格納するために設計されたものを除き、通常のSetであることがわかります。それはどう違いますか?まず、JVMはセットのすべての可能な値を知っています。つまり、すべてのオブジェクトを保存する代わりに、1はアイテムが存在し、0は存在しないことを意味するビットマップを使用できます。これは、セットの順序が順序値の順序、つまり定義された順序であることも意味します。これがこれが印刷される理由です

L XL XXL XXXL

詳細を知りたい場合は、このクラスのソースを読むことをお勧めします。

38
Peter Lawrey

単純なEnumは、一度にoneのみを選択できる値のリストです。あなたの例を使用すると、サイズは特定の布のS、M、Lなどのいずれか1つにしかできません。 Enumの代わりに単純な定数を使用できますが、これには読みやすさ、メンテナンスの容易さ、厳密な型チェックの利点があります。

EnumSetは、変数が同時に複数のEnum値をとる必要がある場合に使用されます。たとえば、画面に書き込むフォントは、bolditalicの両方を同時に使用できます。 EnumSetを使用すると、さまざまな値を追加し、それらのいずれかが実際に設定されているかどうかをいつでもテストできます。 Java他のプログラミング言語から来た場合、これは通常flagsと呼ばれる機能です。

2つを比較します。

enum Size { S, M, L, XL, XXL, XXXL }
Size currentSize;
...
currentSize = Size.S;
...
if (currentSize == Size.S) ...

単一のEnum値を定義、割り当て、チェックします。

enum FontStyle { Bold, Italic, Underline, Strikethrough }
EnumSet<FontStyle> currentStyle;
...
currentStyle = EnumSet.of(FontStyle.Bold, FontStyle.Italic);
...
if (currentStyle.contains(FontStyle.Italic)) ...

定義、2つのEnum値を同時に割り当て、それらの1つが実際に設定されているかどうかを確認します。

37
Gábor

ジョシュア・ブロックの本自体と彼自身の言葉から:

Java.utilパッケージは、単一の列挙型から抽出された値のセットを効率的に表すEnumSetクラスを提供します。このクラスはSetインターフェイスを実装し、他のSet実装で得られる豊富さ、型の安全性、相互運用性をすべて提供します。ただし、内部的には、各EnumSetはビットベクトルとして表されます。基になる列挙型の要素が64個以下(ほとんどの要素)の場合、EnumSet全体が単一のlongで表されるため、そのパフォーマンスはビットフィールドのパフォーマンスに匹敵します。 removeAllやretainAllなどのバルク操作は、ビットフィールドに対して手動で行うのと同じように、ビットごとの演算を使用して実装されます。しかし、手作業によるビット調整のさとエラーの発生から保護されています。 EnumSetはあなたのために大変な仕事をします。

そのため、このようなことができます。

public class SizeSet {

  public enum Size {S, M, L, XL, XXL, XXXL}

  public void applySize(Set<Size> sizes){}

}

それを呼び出すクライアントコードは次のようなことをするかもしれません

SizeSet largeSizeSet = new SizeSet();
largeSizeSet.applySize(EnumSet.of(Size.L, Size.XXL, Size.XXL));

ApplySizeメソッドはSet<Size>ではなくEnumSet<Size>。クライアントがEnumSetをメソッドに渡すことは非常に明白でありそうですが、具体的な実装ではなくインターフェイスを受け入れることをお勧めします。

12
shashwatZing

EnumSetは、特に列挙型要素を保存し、それをすばやく繰り返し処理するために使用されます。例えば。

for (Day d : EnumSet.range(Day.MONDAY, Day.FRIDAY))
        System.out.println(d);

上記のスニペットは、月曜日から金曜日までの曜日を表示します。

7
sambhu

Oracle doc による

列挙セットは、内部的にビットベクトルとして表されます。この表現は非常にコンパクトで効率的です。

読み取り可能、タイプセーフ、低メモリフットプリント...さらに何が必要ですか?

4
jeton

次の例を考えます:

....
public static final String S = "s";
public static final String M = "m";
public static final String L = "l";
....

Set<String> sizeSet = new HashSet<String>();
sizeSet.add(S);
sizeSet.add(M);

それで、上記の例のsizeSetとは何ですか?

EnumSetは上記の例と何も変わりません。ただ、EnumSetは列挙型で動作し、最適化される特別なSet実装であるということだけです。

3
Adrian Shum
EnumSet largeSize

EnumSet largeSizeは、XL、XXL、およびXXXLを含むEnum値のセットです。

Size 

サイズは、定数値S、M、L、XL、XXL、XXXLを持つEnum型のクラスです。

largeSize.iterator()

EnumSetのIteratorは自然な順序、つまり列挙の値が最初に宣言された順序です。

  • EnumSetクラスはJava Collections Frameworkのメンバーであり、同期されていません。
  • 高性能セットの実装であり、HashSetよりもはるかに高速です。
  • 各EnumSetインスタンスのすべての要素は、単一の列挙型の要素でなければなりません。

詳細については、APIドキュメントを参照してください。 http://docs.Oracle.com/javase/8/docs/api/Java/util/EnumSet.html

3
Sarwesh Sethiya

経験則として、列挙値を格納するときは、EnumSetを他のSet実装よりも常に優先する必要があります。

EnumSetを使用することの利点

EnumSetのメソッドは、算術ビット演算を使用して実装されます。これらの計算は非常に高速であるため、すべての基本操作は一定の時間で実行されます。

EnumSetHashSetなどの他のSet実装と比較する場合、値は予測可能な順序で格納され、各計算で1ビットのみを調べる必要があるため、通常は最初のほうが高速です。 HashSetとは異なり、適切なバケットを見つけるためにハッシュコードを計算する必要はありません。

さらに、ビットベクトルの性質により、EnumSetは非常にコンパクトで効率的です。したがって、使用するメモリが少なくなり、すべての利点が得られます。

ソナーソースルールが言う

Setのすべての要素が同じ列挙型の値である場合、SetはEnumSetで置き換えることができます。これは、基になるデータ構造が単純なビットマップであるため、他のセットよりもはるかに効率的です。

EnumMap

ソースは here です

0
yoAlex5

EnumSetは、enumクラスで動作するように特化されたSetコレクションです。 Setインターフェイスを実装し、AbstractSetから拡張します。

enter image description here

EnumSetを使用する場合、いくつかの点を考慮する必要があります。

  1. 列挙値のみを含めることができ、すべての値は同じ列挙に属している必要があります
  2. Null値を追加することはできません。追加しようとするとNullPointerExceptionがスローされます
  3. スレッドセーフではないため、必要に応じて外部で同期する必要があります
  4. 要素は、列挙で宣言された順序に従って格納されます
  5. コピーで動作するフェイルセーフイテレータを使用しているため、コレクションを繰り返し処理するときにコレクションが変更されてもConcurrentModificationExceptionをスローしません

今、EnumSet largeSize部分は変数宣言であるため、はい、EnumSet型です。型の安全性を高めるために、コレクションに要素の型を追加できることに注意してください:EnumSet<Size>

EnumSetの詳細 をご覧ください。

0
Johnny