Panduan untuk EnumSet

1. Pengenalan

Dalam tutorial ini, kita akan meneroka koleksi EnumSet dari pakej java.util dan membincangkan keunikannya.

Mula-mula kami akan menunjukkan ciri-ciri utama koleksi dan selepas itu, kami akan melalui bahagian dalam kelas untuk memahami faedahnya.

Akhirnya, kami akan merangkumi operasi utama yang disediakannya dan melaksanakan beberapa contoh asas.

2. Apa itu EnumSet

An EnumSet ialah khusus Set koleksi untuk kerja dengan enum kelas . Ini menerapkan antara muka Set dan meluas dari AbstractSet :

Walaupun AbstractSet dan AbstractCollection menyediakan implementasi untuk hampir semua kaedah antara muka Set dan Koleksi , EnumSet mengatasi kebanyakannya.

Apabila kita merancang untuk menggunakan EnumSet kita harus mempertimbangkan beberapa perkara penting:

  • Ia hanya boleh mengandungi nilai enum dan semua nilai harus termasuk dalam enum yang sama
  • Itu tidak memungkinkan untuk menambah nilai null , membuang NullPointerException dalam usaha untuk melakukannya
  • Ia tidak selamat untuk benang , jadi kami perlu menyegerakkannya secara luaran jika diperlukan
  • Unsur-unsur disimpan mengikut urutan di mana mereka dinyatakan dalam enum
  • Ia menggunakan iterator fail-safe yang berfungsi pada salinan, jadi ia tidak akan membuang ConcurrentModificationException jika koleksi diubah ketika melakukan iterasi

3. Mengapa Menggunakan EnumSet

Sebagai peraturan, EnumSet harus selalu disukai daripada pelaksanaan Set yang lain ketika kita menyimpan nilai enum .

Di bahagian seterusnya, kita akan melihat apa yang menjadikan koleksi ini lebih baik daripada yang lain. Untuk melakukannya, kami akan menunjukkan secara ringkas kelas dalaman untuk mendapatkan pemahaman yang lebih baik.

3.1. Perincian Pelaksanaan

EnumSet adalah kelas abstrak awam yang mengandungi pelbagai kaedah kilang statik yang membolehkan kita membuat contoh. JDK menyediakan 2 pelaksanaan yang berbeza - bersifat pakej-peribadi dan disokong oleh sedikit vektor:

  • RegularEnumSet dan
  • JumboEnumSet

RegularEnumSet menggunakan satu panjang untuk mewakili vektor bit. Setiap bitelemen panjang mewakili nilai enum . Nilai i-th enum akan disimpan dalam bit i-th, jadi cukup mudah untuk mengetahui sama ada nilai ada atau tidak. Oleh kerana lama adalah jenis data 64-bit, pelaksanaan ini dapat menyimpan hingga 64 elemen.

Sebaliknya, JumboEnumSet menggunakan pelbagai elemen panjang sebagai vektor bit. Ini membolehkan pelaksanaan ini menyimpan lebih daripada 64 elemen. Ia berfungsi seperti RegularEnumSet tetapi membuat beberapa pengiraan tambahan untuk mencari indeks array di mana nilainya disimpan.

Tidak menghairankan, elemen panjang pertama dari array akan menyimpan 64 nilai pertama enum , elemen kedua pada 64 seterusnya, dan seterusnya.

Kaedah kilang EnumSet membuat contoh satu pelaksanaan atau yang lain bergantung pada jumlah elemen enum :

if (universe.length <= 64) return new RegularEnumSet(elementType, universe); else return new JumboEnumSet(elementType, universe);

Perlu diingat bahawa ia hanya mengambil kira ukuran kelas enum , bukan jumlah elemen yang akan disimpan dalam koleksi.

3.2. Keuntungan dari Menggunakan EnumSet

Oleh kerana pelaksanaan EnumSet yang telah kami jelaskan di atas, semua kaedah dalam EnumSet dilaksanakan dengan menggunakan operasi aritmetik bitwise. Pengiraan ini sangat cepat dan oleh itu semua operasi asas dilaksanakan dalam masa yang tetap.

Sekiranya kita membandingkan EnumSet dengan implementasi Set lain seperti HashSet , yang pertama biasanya lebih cepat kerana nilainya disimpan dalam urutan yang dapat diramalkan dan hanya satu bit yang perlu diperiksa untuk setiap pengiraan. Tidak seperti HashSet , tidak perlu menghitung kod hash untuk mencari baldi yang betul.

Lebih-lebih lagi, kerana sifat vektor bit, EnumSet sangat padat dan cekap. Oleh itu, ia menggunakan memori yang lebih sedikit, dengan semua faedah yang dibawanya.

4. Operasi Utama

Sebilangan besar kaedah EnumSet berfungsi seperti Set lain , kecuali kaedah untuk membuat contoh.

Pada bahagian seterusnya, kami akan menunjukkan secara terperinci semua kaedah penciptaan dan kami akan merangkumi sebilangan kaedah yang lain.

Dalam contoh kami, kami akan bekerjasama dengan enum Warna :

public enum Color { RED, YELLOW, GREEN, BLUE, BLACK, WHITE }

4.1. Kaedah Penciptaan

Kaedah yang paling mudah untuk membuat EnumSet adalah allOf () dan noneOf () . Dengan cara ini kita dapat membuat EnumSet dengan mudah mengandungi semua elemen enum Warna kita :

EnumSet.allOf(Color.class);

Begitu juga, kita boleh menggunakan noneOf () untuk melakukan sebaliknya dan membuat koleksi Warna kosong :

EnumSet.noneOf(Color.class);

Sekiranya kita ingin membuat EnumSet dengan subset elemen enum kita boleh menggunakan kaedah () yang terlalu banyak . Penting untuk membezakan antara kaedah dengan bilangan parameter tetap hingga 5 yang berbeza dan kaedah yang menggunakan varargs :

Javadoc menyatakan bahawa prestasi versi varargs dapat lebih lambat daripada yang lain kerana penciptaan array. Oleh itu, kita harus menggunakannya hanya jika kita pada mulanya perlu menambahkan lebih daripada 5 elemen.

Kaedah lain untuk membuat subset enum adalah dengan menggunakan kaedah range () :

EnumSet.range(Color.YELLOW, Color.BLUE);

Dalam contoh di atas, EnumSet mengandungi semua elemen dari Kuning hingga Biru. Mereka mengikuti perintah yang ditentukan dalam enum :

[YELLOW, GREEN, BLUE]

Perhatikan bahawa ia merangkumi elemen pertama dan terakhir yang dinyatakan.

Kaedah kilang lain yang berguna adalah pelengkapOf () yang membolehkan kita mengecualikan elemen yang dilalui sebagai parameter . Mari buat EnumSet dengan semua elemen Warna kecuali hitam dan putih:

EnumSet.complementOf(EnumSet.of(Color.BLACK, Color.WHITE));

Sekiranya kita mencetak koleksi ini, kita dapat melihat bahawa ia mengandungi semua elemen lain:

[RED, YELLOW, GREEN, BLUE]

Akhirnya, kita dapat membuat EnumSet dengan menyalin semua elemen dari EnumSet lain :

EnumSet.copyOf(EnumSet.of(Color.BLACK, Color.WHITE));

Secara dalaman, ia memanggil kaedah klon .

Selain itu, kita juga dapat menyalin semua elemen dari Koleksi mana pun yang mengandungi elemen enum . Mari gunakan untuk menyalin semua elemen senarai:

List colorsList = new ArrayList(); colorsList.add(Color.RED); EnumSet listCopy = EnumSet.copyOf(colorsList);

Dalam kes ini, listCopy hanya mengandungi warna merah.

4.2. Operasi Lain

Selebihnya operasi berfungsi dengan cara yang sama seperti pelaksanaan Set yang lain dan tidak ada perbezaan cara menggunakannya.

Oleh itu, kita dapat membuat EnumSet kosong dengan mudah dan menambahkan beberapa elemen:

EnumSet set = EnumSet.noneOf(Color.class); set.add(Color.RED); set.add(Color.YELLOW)

Periksa sama ada koleksi itu mengandungi unsur tertentu:

set.contains(Color.RED);

Berulang pada elemen:

set.forEach(System.out::println);

Atau hapus elemen:

set.remove(Color.RED);

Ini, tentu saja, antara semua operasi lain yang disokong oleh Set .

5. Kesimpulan

Dalam artikel ini, kami telah menunjukkan ciri-ciri utama EnumSet , pelaksanaan dalamannya dan bagaimana kami dapat memanfaatkannya.

Kami juga telah merangkumi kaedah utama yang ditawarkannya dan menerapkan beberapa contoh untuk menunjukkan bagaimana kami dapat menggunakannya.

Seperti biasa, kod sumber penuh contoh terdapat di GitHub.