Un bucle 'for' para iterar sobre una enumeración en Java

876

Tengo un enumen Java para las direcciones cardinales e intermedias:

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

¿Cómo puedo escribir un forciclo que recorra cada uno de estos enumvalores?

Nick Meyer
fuente

Respuestas:

1400

.values()

Puede llamar al values()método en su enumeración.

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

Este values()método es declarado implícitamente por el compilador . Por lo tanto, no figura en el Enumdocumento.

notnoop
fuente
43
Por qué los valores de este método () no se enumeran aquí en java.lang.enum
jacktrades el
80
@jacktrades: es un método implícito que solo existe en el compilador. Por lo tanto, la clase base no puede declarar un método con el mismo nombre y, por lo tanto, no se incluye en los Javadocs generados automáticamente. docs.oracle.com/javase/specs/jls/se7/html/jls-8.html#jls-8.9.2
Torben
44
Curiosamente, se menciona en los documentos valueOf ()
greg7gkb
129

Se pueden obtener todas las constantes de un tipo enum llamando al public static T[] values()método implícito de ese tipo:

 for (Direction d : Direction.values()) {
     System.out.println(d);
 }
dfa
fuente
@ RAnders00 Verdadero. Pero aún así la respuesta es válida y el formato realmente no importa (al menos para mí)
DARKpRINCE
¿Qué hace el #?
YoTengoUnLCD
@YoTengoUnLCD Básicamente está diciendo que values ​​() es parte del objeto Enum. eg Enum#values()=Enum.values()
Spotlight
Hmm, lo siento, no te sigo, ¿es lo mismo que usar .(siempre)?
YoTengoUnLCD
3
@YoTengoUnLCD El hashtag es la sintaxis JavaDoc, no el código Java.
Jeff G
62

Puede hacer esto de la siguiente manera:

for (Direction direction : EnumSet.allOf(Direction.class)) {
  // do stuff
}
toluju
fuente
1
Siempre que importe java.util.EnumSet
Nate
8
Súper útil para los bucles foreach de Java8. EnumSet.allOf (Enum.class) .forEach (blah -> method (blah))
Hiro2k
1
@ Hiro2k También podría hacerlo Arrays.stream(Enum.values()).forEach(...): la transmisión será secuencial
RAnders00
1
@schatten bueno, es un en setlugar de array. No es "mejor", aunque en mi opinión describe mejor los valores de enumeración, porque desde la definición del conjunto, los valores del conjunto no pueden repetirse (como en la enumeración), mientras que los valores de la matriz pueden serlo.
Jezor
2
@Jezor Es una mejor opción cuando realmente necesita un conjunto muy rápido de enumeraciones, como indicadores de bits, aunque parece ser demasiado complicado para una iteración simple.
schatten
44

Corrientes

Antes de Java 8

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

Java 8

También podemos hacer uso de lambda y streams ( Tutorial ):

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

¿Por qué forEachOrderedy no forEachcon corrientes?

El comportamiento de forEaches explícitamente no determinista donde, a medida que forEachOrderedrealiza una acción para cada elemento de esta secuencia, en el orden de encuentro de la secuencia si la secuencia tiene un orden de encuentro definido. Por forEachlo tanto , no garantiza que se mantenga el pedido.

Además, cuando trabaje con flujos (especialmente los paralelos) tenga en cuenta la naturaleza de los flujos. Según el documento :

Los resultados de la canalización de flujo pueden ser no deterministas o incorrectos si los parámetros de comportamiento para las operaciones de flujo son con estado. Una lambda con estado es aquella cuyo resultado depende de cualquier estado que pueda cambiar durante la ejecución de la canalización de flujo.

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

Aquí, si la operación de mapeo se realiza en paralelo, los resultados para la misma entrada podrían variar de una ejecución a otra, debido a las diferencias de programación de subprocesos, mientras que, con una expresión lambda sin estado, los resultados siempre serían los mismos.

En general, se desaconsejan los efectos secundarios en los parámetros de comportamiento para transmitir las operaciones, ya que a menudo pueden conducir a violaciones involuntarias del requisito de apatridia, así como a otros riesgos de seguridad de hilos.

Las transmisiones pueden o no tener un orden de encuentro definido. Si un flujo tiene o no un orden de encuentro depende de la fuente y de las operaciones intermedias.

akhil_mittal
fuente
Al igual que con todas las operaciones de transmisión, tenga en cuenta la falta de estado de los hilos y los límites de efectos secundarios docs.oracle.com/javase/8/docs/api/java/util/stream/… . Estas 2 opciones de iteración de enumeración son significativamente diferentes a este respecto.
buzz3791
21
for(Direction dir : Direction.values())
{

}
usuario101884
fuente
19

Si no te importa el orden, esto debería funcionar:

Set<Direction> directions = EnumSet.allOf(Direction.class);
for(Direction direction : directions) {
    // do stuff
}
Tom Jefferys
fuente
2
Siempre que importe java.util.EnumSet y java.util.Set
Nate
44
De la documentación paraEnumSet : El iterador devuelto por el método iterador atraviesa los elementos en su orden natural (el orden en que se declaran las constantes enum) . Esto garantiza que el orden de iteración coincida con el orden devuelto por Enum.values().
Jeff G
18
    for (Direction  d : Direction.values()) {
       //your code here   
    }
akf
fuente
5

Java8

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

de Java5 +

for ( Direction d: Direction.values()){
 System.out.println(d);
}
Raghu K Nair
fuente
1
Oh, lo siento. Me acabo de dar cuenta de que akhil_mittal ya ha publicado una respuesta similar.
Raghu K Nair
¿Cuándo y por qué debo usar Stream.of (o) .forEach? El bucle for parece mucho más legible.
Jeremy
No si está familiarizado con la programación funcional.
Alexis Dufrenoy
5

Intenta usar un para cada

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

Más métodos en java 8:

Usando EnumSetconforEach

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

Usando Arrays.asListconforEach

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