Une boucle «pour» pour itérer sur une énumération en Java

876

J'ai un enumen Java pour les directions cardinales et intermédiaires:

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

Comment puis-je écrire une forboucle qui parcourt chacune de ces enumvaleurs?

Nick Meyer
la source

Réponses:

1400

.values()

Vous pouvez appeler la values()méthode sur votre énumération.

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

Cette values()méthode est implicitement déclarée par le compilateur . Il n'est donc pas répertorié dans le Enumdoc.

notnoop
la source
43
Pourquoi cette méthode values ​​() n'est pas répertoriée ici sous java.lang.enum
jacktrades
80
@jacktrades: C'est une méthode implicite qui n'existe que dans le compilateur. Par conséquent, la classe de base ne peut pas déclarer une méthode du même nom et n'est donc pas incluse dans les Javadocs générés automatiquement. docs.oracle.com/javase/specs/jls/se7/html/jls-8.html#jls-8.9.2
Torben
4
Curieusement, il est mentionné dans les documents valueOf ()
greg7gkb
129

Toutes les constantes d'un type enum peuvent être obtenues en appelant la public static T[] values()méthode implicite de ce type:

 for (Direction d : Direction.values()) {
     System.out.println(d);
 }
dfa
la source
@ RAnders00 True. Mais la réponse est toujours valable et le format n'a vraiment pas d'importance (du moins pour moi)
dARKpRINCE
Que fait le #?
YoTengoUnLCD
@YoTengoUnLCD Fondamentalement, cela signifie que values ​​() fait partie de l'objet Enum. par exemple Enum#values()=Enum.values()
Spotlight
Hmm, je suis désolé, je ne suis pas, est-ce la même chose que d'utiliser .(toujours?)?
YoTengoUnLCD
3
@YoTengoUnLCD Le hashtag est la syntaxe JavaDoc, pas le code Java.
Jeff G
62

Vous pouvez le faire comme suit:

for (Direction direction : EnumSet.allOf(Direction.class)) {
  // do stuff
}
toluju
la source
1
Pourvu que vous importiez java.util.EnumSet
Nate
8
Super utile pour les boucles foreach Java8. EnumSet.allOf (Enum.class) .forEach (blah -> method (blah))
Hiro2k
1
@ Hiro2k Vous pourriez aussi le faire Arrays.stream(Enum.values()).forEach(...)- le flux sera séquentiel
RAnders00
1
@ schatten bien, c'est un setlieu de array. Ce n'est pas "mieux", bien qu'il décrive mieux les valeurs d'énumération, car d'après la définition de set, les valeurs de set ne peuvent pas être répétées (comme dans enum), alors que les valeurs dans array peuvent l'être.
Jezor
2
@Jezor C'est un meilleur choix lorsque vous avez réellement besoin d'un ensemble d'énumérations très rapides, comme des indicateurs de bits, mais cela semble trop compliqué pour une simple itération.
schatten
44

Ruisseaux

Avant Java 8

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

Java 8

Nous pouvons également utiliser lambda et les streams ( Tutorial ):

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

Pourquoi forEachOrderedet non forEachavec des streams?

Le comportement de forEachest explicitement non déterministe alors que le forEachOrderedeffectue une action pour chaque élément de ce flux, dans l'ordre de rencontre du flux si le flux a un ordre de rencontre défini. forEachNe garantit donc pas que la commande sera conservée.

De plus, lorsque vous travaillez avec des flux (en particulier des flux parallèles), gardez à l'esprit la nature des flux. Selon le doc :

Les résultats du pipeline de flux peuvent être non déterministes ou incorrects si les paramètres de comportement des opérations de flux sont avec état. Un lambda avec état est un dont le résultat dépend de tout état qui pourrait changer pendant l'exécution du pipeline de flux.

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

Ici, si l'opération de mappage est effectuée en parallèle, les résultats pour la même entrée peuvent varier d'une exécution à l'autre, en raison de différences de planification des threads, tandis qu'avec une expression lambda sans état, les résultats seraient toujours les mêmes.

Les effets secondaires des paramètres de comportement pour les opérations de flux sont, en général, découragés, car ils peuvent souvent conduire à des violations involontaires de l'apatridie, ainsi qu'à d'autres dangers liés à la sécurité des threads.

Les flux peuvent avoir ou non un ordre de rencontre défini. Le fait qu'un flux ait ou non un ordre de rencontre dépend de la source et des opérations intermédiaires.

akhil_mittal
la source
Comme pour toutes les opérations de flux, soyez conscient de l'apatridie des threads et des limites des effets secondaires docs.oracle.com/javase/8/docs/api/java/util/stream/… . Ces deux options d'énumération sont sensiblement différentes à cet égard.
buzz3791
21
for(Direction dir : Direction.values())
{

}
user101884
la source
19

Si vous ne vous souciez pas de la commande, cela devrait fonctionner:

Set<Direction> directions = EnumSet.allOf(Direction.class);
for(Direction direction : directions) {
    // do stuff
}
Tom Jefferys
la source
2
Pourvu que vous importiez java.util.EnumSet et java.util.Set
Nate
4
De la documentation deEnumSet : L'itérateur retourné par la méthode itérateur traverse les éléments dans leur ordre naturel (l'ordre dans lequel les constantes d'énumération sont déclarées) . Cela garantit que l'ordre d'itération correspond à la commande retournée par Enum.values().
Jeff G
18
    for (Direction  d : Direction.values()) {
       //your code here   
    }
akf
la source
5

Java8

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

de Java5 +

for ( Direction d: Direction.values()){
 System.out.println(d);
}
Raghu K Nair
la source
1
Oh pardon. Je viens de réaliser que akhil_mittal a déjà posté la même réponse.
Raghu K Nair le
Quand et pourquoi devrais-je utiliser Stream.of (o) .forEach? La boucle for semble beaucoup plus lisible.
Jeremy
Pas si vous connaissez la programmation fonctionnelle.
Alexis Dufrenoy
5

Essayez d'utiliser un pour chacun

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

Plus de méthodes dans java 8:

Utilisation EnumSetavecforEach

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

Utilisation Arrays.asListavecforEach

Arrays.asList(Direction.values()).forEach(...);
NiVeR
la source