Pętla „for” do iteracji po wyliczeniu w Javie

875

Mam enumJava w kierunkach głównych i pośrednich:

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

Jak napisać forpętlę, która iteruje każdą z tych enumwartości?

Nick Meyer
źródło

Odpowiedzi:

1400

.values()

Możesz wywołać values()metodę na swoim wyliczeniu.

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

Ta values()metoda jest domyślnie zadeklarowana przez kompilator . Więc nie ma go w Enumdokumencie.

notnoop
źródło
43
Dlaczego ta metoda wartości () nie jest wymieniony tutaj pod java.lang.enum
jacktrades
80
@jacktrades: Jest to metoda niejawna, która istnieje tylko w kompilatorze. Dlatego klasa podstawowa nie może zadeklarować metody o tej samej nazwie, a zatem nie zostanie uwzględniona w automatycznie generowanym Javadocs. docs.oracle.com/javase/specs/jls/se7/html/jls-8.html#jls-8.9.2
Torben
4
Dziwnie, jest to wspomniane w dokumentach valueOf ()
greg7gkb
129

Wszystkie stałe typu wyliczeniowego można uzyskać, wywołując public static T[] values()metodę niejawną tego typu:

 for (Direction d : Direction.values()) {
     System.out.println(d);
 }
dfa
źródło
@ RAnders00 Prawda. Ale wciąż odpowiedź jest poprawna, a format naprawdę nie ma znaczenia (przynajmniej dla mnie)
dARKpRINCE
Czego #zrobić?
YoTengoUnLCD
@YoTengoUnLCD Zasadniczo mówi, że wartości () są częścią obiektu Enum. np Enum#values()=Enum.values()
Reflektor
Hmm, przepraszam, nie podążam, czy to to samo, co używanie .(zawsze?)?
YoTengoUnLCD,
3
@YoTengoUnLCD Hashtag to składnia JavaDoc, a nie kod Java.
Jeff G
62

Możesz to zrobić w następujący sposób:

for (Direction direction : EnumSet.allOf(Direction.class)) {
  // do stuff
}
toluju
źródło
1
Pod warunkiem, że zaimportujesz java.util.EnumSet
Nate
8
Super przydatne dla pętli foreach Java8. EnumSet.allOf (Enum.class) .forEach (bla -> method (bla))
Hiro2k
1
@ Hiro2k Można również zrobić Arrays.stream(Enum.values()).forEach(...)- strumień będzie sekwencyjny
RAnders00
1
@ schatten dobrze, to setzamiast array. Nie jest to „lepsze”, chociaż moim zdaniem lepiej opisuje wartości wyliczeniowe, ponieważ z definicji zbioru wartości w zestawie nie mogą się powtarzać (jak w wyliczeniu), podczas gdy wartości w tablicy mogą być.
Jezor
2
@Jezor Jest to lepszy wybór, gdy naprawdę potrzebujesz bardzo szybkiego zestawu wyliczeń, takich jak flagi bitów, choć wydaje się to zbyt skomplikowane, aby można je było po prostu powtórzyć.
schatten
44

Strumienie

Przed Javą 8

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

Java 8

Możemy również korzystać z lambda i strumieni ( samouczek ):

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

Dlaczego forEachOrderedi nie forEachze strumieniami?

Zachowanie forEachjest wyraźnie niedeterministyczne, gdy jako forEachOrderedwykonuje akcję dla każdego elementu tego strumienia, w kolejności spotkań strumienia, jeśli strumień ma zdefiniowaną kolejność spotkań. Tak forEachnie gwarantuje, że zamówienie zostanie utrzymane.

Również podczas pracy ze strumieniami (szczególnie równoległymi) należy pamiętać o naturze strumieni. Zgodnie z dokumentem :

Wyniki potoku strumienia mogą być niedeterministyczne lub niepoprawne, jeśli parametry behawioralne operacji strumienia są stanowe. Stanowa lambda to taka, której wynik zależy od dowolnego stanu, który może się zmienić podczas wykonywania potoku strumienia.

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

Tutaj, jeśli operacja mapowania jest wykonywana równolegle, wyniki dla tego samego wejścia mogą się różnić w zależności od przebiegu, ze względu na różnice w szeregowaniu wątków, podczas gdy przy bezstanowym wyrażeniu lambda wyniki zawsze będą takie same.

Skutki uboczne parametrów behawioralnych podczas operacji strumieniowych są na ogół odradzane, ponieważ często mogą prowadzić do nieświadomego naruszenia wymogu bezpaństwowości, a także innych zagrożeń bezpieczeństwa wątków.

Strumienie mogą mieć określoną kolejność spotkań lub nie. To, czy strumień ma kolejność spotkań, zależy od operacji źródłowej i pośredniej.

akhil_mittal
źródło
Podobnie jak w przypadku wszystkich operacji przesyłania strumieniowego należy pamiętać o bezpaństwowości wątków i ograniczeniach skutków ubocznych docs.oracle.com/javase/8/docs/api/java/util/stream/… . Te dwie opcje iteracji wyliczeniowej różnią się znacznie pod tym względem.
buzz3791
21
for(Direction dir : Direction.values())
{

}
użytkownik101884
źródło
19

Jeśli nie zależy ci na zamówieniu, powinno to działać:

Set<Direction> directions = EnumSet.allOf(Direction.class);
for(Direction direction : directions) {
    // do stuff
}
Tom Jefferys
źródło
2
Pod warunkiem, że importujesz java.util.EnumSet i java.util.Set
Nate
4
Z dokumentacji dlaEnumSet : Iterator zwrócony metodą iteratora przemierza elementy w ich naturalnym porządku (kolejność, w której deklarowane są stałe wyliczeniowe) . Gwarantuje to, że kolejność iteracji odpowiada kolejności zwróconej przez Enum.values().
Jeff G
18
    for (Direction  d : Direction.values()) {
       //your code here   
    }
akf
źródło
5

Java8

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

z Java5 +

for ( Direction d: Direction.values()){
 System.out.println(d);
}
Raghu K Nair
źródło
1
przepraszam. Właśnie zdałem sobie sprawę, że akhil_mittal już opublikował podobną odpowiedź.
Raghu K Nair
Kiedy i dlaczego powinienem używać Stream.of (o) .forEach? Pętla for wydaje się znacznie bardziej czytelna.
Jeremy
Nie, jeśli znasz programowanie funkcjonalne.
Alexis Dufrenoy,
5

Spróbuj użyć dla każdego

for ( Direction direction : Direction.values()){
  System.out.println(direction.toString());
}
Irazza
źródło
4

Więcej metod w java 8:

Korzystanie EnumSetzforEach

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

Korzystanie Arrays.asListzforEach

Arrays.asList(Direction.values()).forEach(...);
NiVeR
źródło