A 'for' loop untuk beralih pada enum di Jawa

876

Saya punya enumdi Java untuk arah mata angin & menengah:

public enum Direction {
   NORTH,
   NORTHEAST,
   EAST,
   SOUTHEAST,
   SOUTH,
   SOUTHWEST,
   WEST,
   NORTHWEST
}

Bagaimana saya bisa menulis forloop yang berulang melalui masing-masing enumnilai - nilai ini ?

Nick Meyer
sumber

Jawaban:

1400

.values()

Anda dapat memanggil values()metode pada enum Anda.

for (Direction dir : Direction.values()) {
  // do what you want
}

Ini values()metode ini secara implisit dinyatakan oleh compiler . Jadi tidak terdaftar di Enumdoc.

tidak ada
sumber
43
Mengapa nilai metode ini () tidak tercantum di sini di bawah java.lang.enum
jacktrades
80
@jacktrades: Ini adalah metode implisit yang hanya ada di kompiler. Oleh karena itu kelas dasar tidak dapat mendeklarasikan metode dengan nama yang sama dan karenanya tidak disertakan dalam Javadocs yang dibuat secara otomatis. docs.oracle.com/javase/specs/jls/se7/html/jls-8.html#jls-8.9.2
Torben
4
Anehnya, ini disebutkan dalam valueOf () docs
greg7gkb
129

Semua konstanta dari tipe enum dapat diperoleh dengan memanggil public static T[] values()metode implisit dari tipe itu:

 for (Direction d : Direction.values()) {
     System.out.println(d);
 }
dfa
sumber
@ RAnders00 Benar. Tapi tetap saja jawabannya valid dan formatnya benar-benar tidak masalah (minimal bagi saya)
dARKpRINCE
Apa yang #dilakukan?
YoTengoUnLCD
@YoTengoUnLCD Pada dasarnya ini mengatakan bahwa nilai () adalah bagian dari objek Enum. misalnya Enum#values()=Enum.values()
Spotlight
Hmm, maaf, saya tidak mengikuti, apakah sama dengan menggunakan .(selalu?)?
YoTengoUnLCD
3
@YoTengoUnLCD Tagar adalah sintaks JavaDoc, bukan kode Java.
Jeff G
62

Anda dapat melakukan ini sebagai berikut:

for (Direction direction : EnumSet.allOf(Direction.class)) {
  // do stuff
}
toluju
sumber
1
Asalkan Anda mengimpor java.util.EnumSet
Nate
8
Super berguna untuk Java8 foreach loop. EnumSet.allOf (Enum.class) .forEach (bla -> method (bla))
Hiro2k
1
@ Hiro2k Anda juga bisa melakukannya Arrays.stream(Enum.values()).forEach(...)- alirannya akan berurutan
RAnders00
1
@schatten yah, ini setbukan array. Ini bukan "lebih baik", meskipun itu menggambarkan nilai enum lebih baik menurut saya, karena dari definisi set, nilai-nilai dalam set tidak dapat diulangi (seperti dalam enum), sedangkan nilai-nilai dalam array dapat.
Jezor
2
@Jezor Ini adalah pilihan yang lebih baik ketika Anda benar-benar membutuhkan set enum yang sangat cepat, seperti bendera bit, meskipun tampaknya terlalu rumit untuk iterasi sederhana.
schatten
44

Streaming

Sebelum ke Jawa 8

for (Direction dir : Direction.values()) {
            System.out.println(dir);
}

Java 8

Kami juga dapat menggunakan lambda dan stream ( Tutorial ):

Stream.of(Direction.values()).forEachOrdered(System.out::println);

Kenapa forEachOrdereddan tidakforEach dengan stream?

Perilaku forEacheksplisit nondeterministik di mana sebagai forEachOrderedmelakukan tindakan untuk setiap elemen aliran ini, dalam urutan pertemuan aliran jika aliran memiliki urutan pertemuan yang ditentukan. Jadi forEachtidak menjamin bahwa pesanan akan disimpan.

Juga ketika bekerja dengan stream (terutama yang paralel) perlu diingat sifat stream. Sesuai dokumen :

Hasil aliran pipa mungkin tidak deterministik atau salah jika parameter perilaku ke operasi aliran stateful. Lambda stateful adalah salah satu yang hasilnya tergantung pada negara yang mungkin berubah selama pelaksanaan pipa aliran.

Set<Integer> seen = Collections.synchronizedSet(new HashSet<>());
stream.parallel().map(e -> { if (seen.add(e)) return 0; else return e; })...

Di sini, jika operasi pemetaan dilakukan secara paralel, hasil untuk input yang sama dapat bervariasi dari satu menjalankan ke menjalankan, karena perbedaan penjadwalan thread, sedangkan, dengan ekspresi lambda stateless, hasilnya akan selalu sama.

Efek samping dalam parameter perilaku untuk mengalirkan operasi, secara umum, tidak disarankan, karena seringkali dapat menyebabkan pelanggaran tanpa disadari terhadap persyaratan kewarganegaraan, serta bahaya keselamatan benang lainnya.

Streaming mungkin atau mungkin tidak memiliki urutan pertemuan yang ditentukan. Apakah aliran memiliki urutan pertemuan atau tidak tergantung pada sumber dan operasi perantara.

akhil_mittal
sumber
Seperti halnya semua operasi streaming, sadari kewarganegaraan utas dan batas efek samping, docs.oracle.com/javase/8/docs/api/java/util/stream/… . Kedua opsi iterasi ini berbeda secara signifikan dalam hal ini.
buzz3791
21
for(Direction dir : Direction.values())
{

}
pengguna101884
sumber
19

Jika Anda tidak peduli dengan pesanan ini, ini akan berfungsi:

Set<Direction> directions = EnumSet.allOf(Direction.class);
for(Direction direction : directions) {
    // do stuff
}
Tom Jefferys
sumber
2
Asalkan Anda mengimpor java.util.EnumSet dan java.util.Set
Nate
4
Dari dokumentasi untukEnumSet : Iterator yang dikembalikan oleh metode iterator melintasi elemen dalam tatanan alami mereka (urutan di mana konstanta enum dinyatakan) . Ini menjamin bahwa urutan iterasi cocok dengan pesanan yang dikembalikan oleh Enum.values().
Jeff G
18
    for (Direction  d : Direction.values()) {
       //your code here   
    }
akf
sumber
5

Java8

Stream.of(Direction.values()).forEach(System.out::println);

dari Java5 +

for ( Direction d: Direction.values()){
 System.out.println(d);
}
Raghu K Nair
sumber
1
Oh maaf. Saya baru menyadari bahwa akhil_mittal sudah memposting jawaban yang sama.
Raghu K Nair
Kapan dan mengapa saya harus menggunakan Stream.of (o) .forEach? Untuk loop tampaknya jauh lebih mudah dibaca.
Jeremy
Tidak jika Anda terbiasa dengan pemrograman fungsional.
Alexis Dufrenoy
5

Cobalah untuk menggunakan masing-masing

for ( Direction direction : Direction.values()){
  System.out.println(direction.toString());
}
Irazza
sumber
4

Lebih banyak metode di java 8:

Menggunakan EnumSetdenganforEach

EnumSet.allOf(Direction.class).forEach(...);

Menggunakan Arrays.asListdenganforEach

Arrays.asList(Direction.values()).forEach(...);
NiVeR
sumber