Um loop 'for' para iterar sobre uma enumeração em Java

876

Eu tenho um enumem Java para as direções cardinal e intermediária:

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

Como posso escrever um forloop que itera através de cada um desses enumvalores?

Nick Meyer
fonte

Respostas:

1400

.values()

Você pode chamar o values()método na sua enumeração.

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

Este values()método é declarado implicitamente pelo compilador . Portanto, não está listado no Enumdocumento

notnoop
fonte
43
Por este método valores () não está listado aqui sob java.lang.Enum
jacktrades
80
@ jacktrades: É um método implícito que existe apenas no compilador. Portanto, a classe base não pode declarar um método com o mesmo nome e, portanto, não é incluído nos Javadocs gerados automaticamente. docs.oracle.com/javase/specs/jls/se7/html/jls-8.html#jls-8.9.2
Torben
4
Estranhamente, isso é mencionado nos documentos valueOf ()
greg7gkb
129

Todas as constantes de um tipo de enum podem ser obtidas chamando o public static T[] values()método implícito desse tipo:

 for (Direction d : Direction.values()) {
     System.out.println(d);
 }
dfa
fonte
@ RAnders00 True. Mas ainda assim a resposta é válida e o formato realmente não importa (pelo menos para mim)
dARKpRINCE
O que #faz?
YoTengoUnLCD
@YoTengoUnLCD Basicamente, está dizendo que values ​​() faz parte do objeto Enum. por exemplo Enum#values()=Enum.values()
Spotlight
Hmm, desculpe, eu não sigo, é o mesmo que usar .(sempre?)?
YoTengoUnLCD
3
@YoTengoUnLCD A hashtag é uma sintaxe JavaDoc, não um código Java.
Jeff G
62

Você pode fazer isso da seguinte maneira:

for (Direction direction : EnumSet.allOf(Direction.class)) {
  // do stuff
}
toluju
fonte
1
Desde que você importar java.util.EnumSet
Nate
8
Super útil para Java8 foreach loops. EnumSet.allOf (Enum.class) .forEach (blah -> method (blah))
Hiro2k
1
@ Hiro2k Você também pode fazer Arrays.stream(Enum.values()).forEach(...)- o fluxo será seqüencial #
RAnders00 8/16/16
1
@ Chatchat bem, é um em setvez de array. Não é "melhor", embora descreva valores de enum melhor na minha opinião, porque da definição de conjunto, os valores em conjunto não podem ser repetidos (como em enum), enquanto os valores em matriz podem ser.
Jezor
2
@Jezor É uma escolha melhor quando você realmente precisa de um conjunto muito rápido de enumerações, como sinalizadores de bits, embora pareça ser muito complicado para uma iteração simples.
schatten
44

Streams

Antes do Java 8

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

Java 8

Também podemos usar lambda e streams ( Tutorial ):

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

Por que forEachOrderede não forEachcom fluxos?

O comportamento de forEaché explicitamente não determinístico, onde comoforEachOrdered executa uma ação para cada elemento desse fluxo, na ordem de encontro do fluxo, se o fluxo tiver uma ordem de encontro definida. assimforEach , não garante que o pedido seja mantido.

Além disso, ao trabalhar com fluxos (especialmente os paralelos), lembre-se da natureza dos fluxos. De acordo com o documento :

Os resultados do pipeline de fluxo podem não ser determinísticos ou incorretos se os parâmetros comportamentais para as operações de fluxo forem stateful. Um lambda com estado é aquele cujo resultado depende de qualquer estado que possa mudar durante a execução do pipeline de fluxo.

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

Aqui, se a operação de mapeamento for executada em paralelo, os resultados para a mesma entrada podem variar de execução para execução, devido a diferenças de planejamento de encadeamento, enquanto que, com uma expressão lambda sem estado, os resultados sempre serão os mesmos.

Os efeitos colaterais nos parâmetros comportamentais das operações de fluxo são, em geral, desencorajados, pois geralmente podem levar a violações involuntárias do requisito de apatridia, bem como a outros riscos de segurança da thread.

Os fluxos podem ou não ter uma ordem de encontro definida. O fato de um fluxo ter ou não uma ordem de encontro depende da origem e das operações intermediárias.

akhil_mittal
fonte
Como em todas as operações de fluxo, esteja ciente da ausência de estado do thread e dos limites de efeito colateral docs.oracle.com/javase/8/docs/api/java/util/stream/… . Essas duas opções de iteração de enum são significativamente diferentes nesse sentido.
precisa saber é o seguinte
21
for(Direction dir : Direction.values())
{

}
user101884
fonte
19

Se você não se importa com o pedido, isso deve funcionar:

Set<Direction> directions = EnumSet.allOf(Direction.class);
for(Direction direction : directions) {
    // do stuff
}
Tom Jefferys
fonte
2
Desde que você importar java.util.EnumSet e java.util.Set
Nate
4
Da documentação paraEnumSet : O iterador retornado pelo método do iterador percorre os elementos em sua ordem natural (a ordem na qual as constantes da enumeração são declaradas) . Isso garante que a ordem da iteração corresponda à ordem retornada por Enum.values().
Jeff G
18
    for (Direction  d : Direction.values()) {
       //your code here   
    }
akf
fonte
5

Java8

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

do Java5 +

for ( Direction d: Direction.values()){
 System.out.println(d);
}
Raghu K Nair
fonte
1
Oh, desculpe. Acabei de perceber que akhil_mittal já postou a resposta semelhante.
Raghu K Nair
Quando e por que devo usar o Stream.of (o) .forEch? O loop for parece muito mais legível.
Jeremy
Não se você estiver familiarizado com a programação funcional.
Alexis Dufrenoy
5

Tente usar um para cada

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

Mais métodos em java 8:

Usando EnumSetcomforEach

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

Usando Arrays.asListcomforEach

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