Un ciclo 'for' per iterare su un enum in Java


Risposte:


1400

.values()

Puoi chiamare il values()metodo sul tuo enum.

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

Questo values()metodo è implicitamente dichiarato dal compilatore . Quindi non è elencato su Enumdoc.


43
Perché i valori di questo metodo () non sono elencati qui sotto java.lang.enum
jacktrades il

80
@jacktrades: è un metodo implicito che esiste solo nel compilatore. Pertanto la classe base non può dichiarare un metodo con lo stesso nome e quindi non viene inclusa nel Javadocs generato automaticamente. docs.oracle.com/javase/specs/jls/se7/html/jls-8.html#jls-8.9.2
Torben

4
Stranamente, è menzionato nei documenti valueOf ()
greg7gkb,

129

Tutte le costanti di un tipo enum possono essere ottenute chiamando il public static T[] values()metodo implicito di quel tipo:

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

@ RAnders00 True. Ma la risposta è ancora valida e il formato non ha davvero importanza (almeno per me)
DARKpRINCE

Che cosa #fa?
YoTengoUnLCD,

@YoTengoUnLCD In sostanza sta dicendo che valori () fa parte dell'oggetto Enum. ad es. Enum#values()=Enum.values()
Spotlight l'

Hmm, mi dispiace, non lo seguo, è come usare .(sempre?)?
YoTengoUnLCD,

3
@YoTengoUnLCD L'hashtag è la sintassi JavaDoc, non il codice Java.
Jeff G

62

Puoi farlo come segue:

for (Direction direction : EnumSet.allOf(Direction.class)) {
  // do stuff
}

1
A condizione che tu abbia importato java.util.EnumSet
Nate

8
Super utile per i cicli foreach Java8. EnumSet.allOf (Enum.class) .forEach (blah -> method (blah))
Hiro2k

1
@ Hiro2k Potresti anche fare Arrays.stream(Enum.values()).forEach(...)- lo stream sarà sequenziale
RAnders00

1
@schatten bene, è un setinvece di array. Non è "migliore", sebbene descriva meglio i valori enum secondo me, perché dalla definizione di set, i valori in set non possono essere ripetuti (come in enum), mentre i valori in array possono essere.
Jezor,

2
@Jezor È una scelta migliore quando in realtà hai bisogno di un set di enumerazioni molto veloci, come bit flags, anche se sembra essere troppo complicato per una semplice iterazione.
Schatten,

44

Flussi

Prima di Java 8

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

Java 8

Possiamo anche utilizzare lambda e stream ( Tutorial ):

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

Perché forEachOrderede non forEachcon i flussi?

Il comportamento di forEach è esplicitamente non deterministico dove come forEachOrderedesegue un'azione per ciascun elemento di questo flusso, nell'ordine di incontro del flusso se il flusso ha un ordine di incontro definito. Quindi forEachnon garantisce che l'ordine verrà mantenuto.

Inoltre, quando si lavora con flussi (in particolare quelli paralleli), tenere presente la natura dei flussi. Secondo il documento :

I risultati della pipeline del flusso possono essere non deterministici o errati se i parametri comportamentali per le operazioni del flusso sono stateful. Un lambda con stato è uno il cui risultato dipende da qualsiasi stato che potrebbe cambiare durante l'esecuzione della pipeline del flusso.

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

In questo caso, se l'operazione di mappatura viene eseguita in parallelo, i risultati per lo stesso input potrebbero variare da un'esecuzione all'altra, a causa delle differenze di pianificazione del thread, mentre, con un'espressione lambda senza stato, i risultati sarebbero sempre gli stessi.

Gli effetti collaterali nei parametri comportamentali per le operazioni di streaming sono, in generale, scoraggiati, poiché spesso possono portare a involontarie violazioni del requisito di apolidia, nonché ad altri pericoli per la sicurezza dei thread.

Gli stream possono avere o meno un ordine di incontro definito. Il fatto che uno stream abbia o meno un ordine di incontro dipende dalla sorgente e dalle operazioni intermedie.


Come per tutte le operazioni di streaming, tenere presente l'apolidia dei thread e i limiti degli effetti collaterali docs.oracle.com/javase/8/docs/api/java/util/stream/… . Queste 2 opzioni di iterazione enumerativa sono significativamente diverse in questo senso.
buzz3791,


19

Se non ti interessa l'ordine, dovrebbe funzionare:

Set<Direction> directions = EnumSet.allOf(Direction.class);
for(Direction direction : directions) {
    // do stuff
}

2
Fornito importare java.util.EnumSet e java.util.Set
Nate

4
Dalla documentazione perEnumSet : L'iteratore restituito dal metodo iteratore attraversa gli elementi nel loro ordine naturale (l'ordine in cui sono dichiarate le costanti enum) . Ciò garantisce che l'ordine di iterazione corrisponda all'ordine restituito da Enum.values().
Jeff G

18
    for (Direction  d : Direction.values()) {
       //your code here   
    }

5

Java8

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

da Java5 +

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

1
Oh scusa. Ho appena realizzato che akhil_mittal ha già pubblicato la risposta simile.
Raghu K Nair,

Quando e perché dovrei usare Stream.of (o) .forEach? Il ciclo for sembra molto più leggibile.
Jeremy,

Non se hai familiarità con la programmazione funzionale.
Alexis Dufrenoy,

5

Prova a usare a per ciascuno

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

4

Altri metodi in java 8:

Usando EnumSetconforEach

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

Usando Arrays.asListconforEach

Arrays.asList(Direction.values()).forEach(...);
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.