Eine 'for'-Schleife zum Durchlaufen einer Aufzählung in Java

876

Ich habe eine enumin Java für die Kardinal- und Zwischenrichtungen:

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

Wie kann ich eine forSchleife schreiben , die jeden dieser enumWerte durchläuft ?

Nick Meyer
quelle

Antworten:

1400

.values()

Sie können die values()Methode in Ihrer Enumeration aufrufen .

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

Diese values()Methode wird vom Compiler implizit deklariert . Es ist also nicht in Enumdoc aufgeführt.

notnoop
quelle
43
Warum diese Methode values () nicht aufgeführt ist hier unter java.lang.Enum
jacktrades
80
@jacktrades: Dies ist eine implizite Methode, die nur im Compiler vorhanden ist. Daher kann die Basisklasse keine Methode mit demselben Namen deklarieren und wird daher nicht in die automatisch generierten Javadocs aufgenommen. docs.oracle.com/javase/specs/jls/se7/html/jls-8.html#jls-8.9.2
Torben
4
Seltsamerweise wird es in den valueOf ()
-Dokumenten
129

Alle Konstanten eines Aufzählungstyps können durch Aufrufen der impliziten public static T[] values()Methode dieses Typs erhalten werden:

 for (Direction d : Direction.values()) {
     System.out.println(d);
 }
dfa
quelle
@ RAnders00 True. Aber immer noch ist die Antwort gültig und das Format spielt wirklich keine Rolle (zumindest für mich)
DARKpRINCE
Was macht das #?
YoTengoUnLCD
@YoTengoUnLCD Grundsätzlich heißt es, dass values ​​() Teil des Enum-Objekts ist. zB Enum#values()=Enum.values()
Spotlight
Hmm, es tut mir leid, ich folge nicht, ist es das gleiche wie mit .(immer?)?
YoTengoUnLCD
3
@YoTengoUnLCD Das Hashtag ist JavaDoc-Syntax, kein Java-Code.
Jeff G
62

Sie können dies wie folgt tun:

for (Direction direction : EnumSet.allOf(Direction.class)) {
  // do stuff
}
Toluju
quelle
1
Vorausgesetzt, Sie importieren java.util.EnumSet
Nate
8
Super nützlich für Java8 foreach-Schleifen. EnumSet.allOf (Enum.class) .forEach (bla -> Methode (bla))
Hiro2k
1
@ Hiro2k Sie könnten auch tun Arrays.stream(Enum.values()).forEach(...)- der Stream wird sequentiell sein
RAnders00
1
@schatten gut, es ist ein setstatt array. Es ist nicht "besser", obwohl es meiner Meinung nach Aufzählungswerte besser beschreibt, da nach der Definition von set Werte in set nicht wiederholt werden können (wie in enum), wohingegen Werte in Array sein können.
Jezor
2
@Jezor Es ist eine bessere Wahl, wenn Sie tatsächlich einen sehr schnellen Satz von Aufzählungen wie Bit-Flags benötigen, obwohl dies für eine einfache Iteration zu kompliziert zu sein scheint.
schatten
44

Streams

Vor Java 8

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

Java 8

Wir können auch Lambda und Streams verwenden ( Tutorial ):

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

Warum forEachOrderedund nicht forEachmit Streams?

Das Verhalten von forEachist explizit nicht deterministisch, wenn der forEachOrderedBenutzer eine Aktion für jedes Element dieses Streams in der Begegnungsreihenfolge des Streams ausführt, wenn der Stream eine definierte Begegnungsreihenfolge hat. DamitforEach garantiert nicht , dass die Reihenfolge gehalten werden würde.

Beachten Sie auch bei der Arbeit mit Streams (insbesondere parallelen) die Art der Streams. Nach dem Dokument :

Die Ergebnisse der Stream-Pipeline sind möglicherweise nicht deterministisch oder falsch, wenn die Verhaltensparameter für die Stream-Operationen statusbehaftet sind. Ein Stateful Lambda ist eines, dessen Ergebnis von jedem Zustand abhängt, der sich während der Ausführung der Stream-Pipeline ändern kann.

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

Wenn hier die Zuordnungsoperation parallel ausgeführt wird, können die Ergebnisse für dieselbe Eingabe aufgrund von Unterschieden bei der Thread-Planung von Lauf zu Lauf variieren, während bei einem zustandslosen Lambda-Ausdruck die Ergebnisse immer dieselben wären.

Nebenwirkungen von Verhaltensparametern bei Stream-Vorgängen werden im Allgemeinen nicht empfohlen, da sie häufig zu unwissentlichen Verstößen gegen die Anforderung der Staatenlosigkeit sowie zu anderen Sicherheitsrisiken für Threads führen können.

Streams können eine definierte Begegnungsreihenfolge haben oder nicht. Ob ein Stream eine Begegnungsreihenfolge hat oder nicht, hängt von der Quelle und den Zwischenoperationen ab.

akhil_mittal
quelle
Wie bei allen Stream-Vorgängen sollten Sie sich der Statuslosigkeit des Threads und der Einschränkungen für Nebenwirkungen bewusst sein . Docs.oracle.com/javase/8/docs/api/java/util/stream/… . Diese 2 Aufzählungsiterationsoptionen unterscheiden sich in dieser Hinsicht erheblich.
Buzz3791
21
for(Direction dir : Direction.values())
{

}
user101884
quelle
19

Wenn Sie sich nicht für die Reihenfolge interessieren, sollte dies funktionieren:

Set<Direction> directions = EnumSet.allOf(Direction.class);
for(Direction direction : directions) {
    // do stuff
}
Tom Jefferys
quelle
2
Vorausgesetzt, Sie importieren java.util.EnumSet und java.util.Set
Nate
4
Aus der Dokumentation fürEnumSet : Der von der Iterator-Methode zurückgegebene Iterator durchläuft die Elemente in ihrer natürlichen Reihenfolge (der Reihenfolge, in der die Enum-Konstanten deklariert werden) . Dies garantiert, dass die Reihenfolge der Iteration mit der von zurückgegebenen Reihenfolge übereinstimmt Enum.values().
Jeff G
18
    for (Direction  d : Direction.values()) {
       //your code here   
    }
akf
quelle
5

Java8

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

von Java5 +

for ( Direction d: Direction.values()){
 System.out.println(d);
}
Raghu K Nair
quelle
1
Oh, das tut mir leid. Ich habe gerade festgestellt, dass akhil_mittal bereits die ähnliche Antwort gepostet hat.
Raghu K Nair
Wann und warum sollte ich Stream.of (o) .forEach verwenden? Die for-Schleife scheint viel besser lesbar zu sein.
Jeremy
Nicht, wenn Sie mit funktionaler Programmierung vertraut sind.
Alexis Dufrenoy
5

Versuchen Sie, jeweils einen zu verwenden

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

Weitere Methoden in Java 8:

Verwenden EnumSetmitforEach

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

Verwenden Arrays.asListmitforEach

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