私は次の例を持っています:
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型のオブジェクトですか?それは本当にどういう意味ですか?もっとよく理解したいです。
変数については、その型は宣言で見つかります。
EnumSet largeSize
はい、largeSize
(コレクションなのでlargeSizes
という名前にする必要があります)はEnumSet
型です。また、生成される必要があるため、次のように宣言する必要があります。
EnumSet<Size> largeSizes
つまり、largeSizes
はEnumSet
型です。 EnumSet
は、特定の列挙型の列挙インスタンスを含むSet
であり、他のSet
実装(HashSet
、TreeSet
など、より効率的な方法で等。)。 EnumSet
が何であるかを知るには、その [〜#〜] api [〜#〜] を読んでください。
コードを簡素化する
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
詳細を知りたい場合は、このクラスのソースを読むことをお勧めします。
単純なEnum
は、一度にoneのみを選択できる値のリストです。あなたの例を使用すると、サイズは特定の布のS、M、Lなどのいずれか1つにしかできません。 Enum
の代わりに単純な定数を使用できますが、これには読みやすさ、メンテナンスの容易さ、厳密な型チェックの利点があります。
EnumSet
は、変数が同時に複数のEnum
値をとる必要がある場合に使用されます。たとえば、画面に書き込むフォントは、boldとitalicの両方を同時に使用できます。 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つが実際に設定されているかどうかを確認します。
ジョシュア・ブロックの本自体と彼自身の言葉から:
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をメソッドに渡すことは非常に明白でありそうですが、具体的な実装ではなくインターフェイスを受け入れることをお勧めします。
EnumSetは、特に列挙型要素を保存し、それをすばやく繰り返し処理するために使用されます。例えば。
for (Day d : EnumSet.range(Day.MONDAY, Day.FRIDAY))
System.out.println(d);
上記のスニペットは、月曜日から金曜日までの曜日を表示します。
Oracle doc による
列挙セットは、内部的にビットベクトルとして表されます。この表現は非常にコンパクトで効率的です。
読み取り可能、タイプセーフ、低メモリフットプリント...さらに何が必要ですか?
次の例を考えます:
....
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実装であるということだけです。
EnumSet largeSize
EnumSet largeSizeは、XL、XXL、およびXXXLを含むEnum値のセットです。
Size
サイズは、定数値S、M、L、XL、XXL、XXXLを持つEnum型のクラスです。
largeSize.iterator()
EnumSetのIteratorは自然な順序、つまり列挙の値が最初に宣言された順序です。
詳細については、APIドキュメントを参照してください。 http://docs.Oracle.com/javase/8/docs/api/Java/util/EnumSet.html
経験則として、列挙値を格納するときは、EnumSet
を他のSet実装よりも常に優先する必要があります。
EnumSet
:を使用することの利点
EnumSet
のメソッドは、算術ビット演算を使用して実装されます。これらの計算は非常に高速であるため、すべての基本操作は一定の時間で実行されます。
EnumSet
をHashSet
などの他のSet実装と比較する場合、値は予測可能な順序で格納され、各計算で1ビットのみを調べる必要があるため、通常は最初のほうが高速です。 HashSetとは異なり、適切なバケットを見つけるためにハッシュコードを計算する必要はありません。
さらに、ビットベクトルの性質により、EnumSet
は非常にコンパクトで効率的です。したがって、使用するメモリが少なくなり、すべての利点が得られます。
Setのすべての要素が同じ列挙型の値である場合、SetはEnumSetで置き換えることができます。これは、基になるデータ構造が単純なビットマップであるため、他のセットよりもはるかに効率的です。
ソースは here です
EnumSet
は、enumクラスで動作するように特化されたSetコレクションです。 Set
インターフェイスを実装し、AbstractSet
から拡張します。
EnumSetを使用する場合、いくつかの点を考慮する必要があります。
今、EnumSet largeSize
部分は変数宣言であるため、はい、EnumSet型です。型の安全性を高めるために、コレクションに要素の型を追加できることに注意してください:EnumSet<Size>
EnumSetの詳細 をご覧ください。