934

I have an enum in Java for the cardinal and intermediate directions:

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

How can I write a for loop that iterates through each of these enum values?

Mateen Ulhaq
  • 24,552
  • 19
  • 101
  • 135
Nick Meyer
  • 39,212
  • 14
  • 67
  • 75

9 Answers9

1480

.values()

You can call the values() method on your enum.

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

This values() method is implicitly declared by the compiler. So it is not listed on Enum doc.

Basil Bourque
  • 303,325
  • 100
  • 852
  • 1,154
notnoop
  • 58,763
  • 21
  • 123
  • 144
  • 46
    Why this method *values()* isn't listed [here](http://docs.oracle.com/javase/7/docs/api/) under java.lang.enum – jacktrades Jan 17 '13 at 01:12
  • 83
    @jacktrades: It is an implicit method that exists only in the compiler. Therefore the base class can not declare a method with the same name and thus it does not get included in the automatically generated Javadocs. http://docs.oracle.com/javase/specs/jls/se7/html/jls-8.html#jls-8.9.2 – Torben Mar 05 '13 at 09:32
  • 4
    Oddly, it is mentioned in the [valueOf() docs](http://docs.oracle.com/javase/7/docs/api/java/lang/Enum.html#valueOf(java.lang.Class,%20java.lang.String)) – greg7gkb Sep 03 '17 at 22:11
141

All the constants of an enum type can be obtained by calling the implicit public static T[] values() method of that type:

 for (Direction d : Direction.values()) {
     System.out.println(d);
 }
dfa
  • 114,442
  • 31
  • 189
  • 228
64

You can do this as follows:

for (Direction direction : EnumSet.allOf(Direction.class)) {
  // do stuff
}
toluju
  • 4,097
  • 2
  • 23
  • 27
  • 2
    Provided you import java.util.EnumSet – Nate Jul 09 '09 at 17:13
  • 9
    Super useful for Java8 foreach loops. EnumSet.allOf(Enum.class).forEach(blah -> method(blah)) – Hiro2k Jun 02 '15 at 18:18
  • 1
    @Hiro2k You could also do `Arrays.stream(Enum.values()).forEach(...)` - the stream will be sequential – randers Feb 08 '16 at 12:42
  • Can you explain why it's better than `Enum.values()` ? – schatten May 13 '16 at 23:02
  • 1
    @schatten well, it's a `set` instead of `array`. It's not "better", although it describes enum values better in my opinion, because from set's definition, values in set cannot be repeated (like in enum), whereas values in array can be. – Jezor Sep 08 '16 at 13:56
  • 2
    @Jezor It's a better choice when you actually need a very fast set of enums, like bit flags, though seems to be too complicated for a simple iteration. – schatten Sep 08 '16 at 19:02
46

Streams

Prior to Java 8

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

Java 8

We can also make use of lambda and streams (Tutorial):

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

Why forEachOrdered and not forEach with streams ?

The behaviour of forEach is explicitly nondeterministic where as the forEachOrdered performs an action for each element of this stream, in the encounter order of the stream if the stream has a defined encounter order. So forEach does not guarantee that the order would be kept.

Also when working with streams (especially parallel ones) keep in mind the nature of streams. As per the doc:

Stream pipeline results may be nondeterministic or incorrect if the behavioral parameters to the stream operations are stateful. A stateful lambda is one whose result depends on any state which might change during the execution of the stream pipeline.

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

Here, if the mapping operation is performed in parallel, the results for the same input could vary from run to run, due to thread scheduling differences, whereas, with a stateless lambda expression the results would always be the same.

Side-effects in behavioral parameters to stream operations are, in general, discouraged, as they can often lead to unwitting violations of the statelessness requirement, as well as other thread-safety hazards.

Streams may or may not have a defined encounter order. Whether or not a stream has an encounter order depends on the source and the intermediate operations.

akhil_mittal
  • 23,309
  • 7
  • 96
  • 95
  • 1
    As with all stream operations be aware of thread statelessness and side effect limits https://docs.oracle.com/javase/8/docs/api/java/util/stream/package-summary.html#Statelessness. These 2 enum iteration options are significantly different in this regard. – buzz3791 Dec 04 '18 at 23:10
21

If you don't care about the order this should work:

Set<Direction> directions = EnumSet.allOf(Direction.class);
for(Direction direction : directions) {
    // do stuff
}
Tom Jefferys
  • 13,090
  • 2
  • 35
  • 36
  • 2
    Provided you import java.util.EnumSet and java.util.Set – Nate Jul 09 '09 at 17:15
  • 4
    From the [documentation for `EnumSet`](https://docs.oracle.com/javase/8/docs/api/java/util/EnumSet.html): *The iterator returned by the iterator method traverses the elements in their **natural order** (the order in which the enum constants are declared)*. This guarantees that the order of iteration matches the order returned by `Enum.values()`. – Jeff G Oct 31 '16 at 20:23
7

Java8

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

from Java5+

for ( Direction d: Direction.values()){
 System.out.println(d);
}
Raghu K Nair
  • 3,854
  • 1
  • 28
  • 45
5

More methods in java 8:

Using EnumSet with forEach

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

Using Arrays.asList with forEach

Arrays.asList(Direction.values()).forEach(...);
NiVeR
  • 9,644
  • 4
  • 30
  • 35
2

we can use a filter(JAVA 8) like this.

Stream.of(Direction.values()).filter(name -> !name.toString().startsWith("S")).forEach(System.out::println);
HK boy
  • 1,398
  • 11
  • 17
  • 25
Sarat Kumar
  • 101
  • 1
  • 8
2

Scenario: Let's say, we have a fixed number of card types. Each card type has fees and a joining bonus associated with it.

package enumPkg;

public enum CardTypes {
//Each enum is object
DEBIT(10,20),
CREDIT(0,10),
CRYPTO(5,30);

//Object properties
int fees;
int bonus;

//Initilize object using constructor
CardTypes(int fee, int bonus){
    this.fees = fee;
    this.bonus = bonus;
}

//access object property
public int getFees(){
    return this.fees;
}

public int getBonus(){
    return this.bonus;
}

}

Now to access enum in other class. Follow the below process in java:

package enumPkg;

public class EnumClass {
public static void main(String[] args) {
    CardTypes cardType = CardTypes.CREDIT; //Each enum element is public static final, when accessed returns a object
    System.out.println(cardType);

    System.out.println("Debit card fees : "+CardTypes.DEBIT.getFees());
    System.out.println("Debit card bonus : "+CardTypes.DEBIT.getBonus());

    CardTypes[] cardTypes = CardTypes.values();//return array of CardTypes i.e all enum elements we have defined

    for (CardTypes type : CardTypes.values()) {
        System.out.println(type); //particular enum object
        System.out.println(type.ordinal()); //return enum position
        System.out.println("Bonus : "+type.getBonus()); //return enum object property: Bonus
        System.out.println("Fees  : "+type.getFees());//return enum object property: Fees
    }

}
}

Output:

CREDIT
Debit card fees : 10
Debit card bonus : 20
DEBIT
0
Bonus : 20
Fees  : 10
CREDIT
1
Bonus : 10
Fees  : 0
CRYPTO
2
Bonus : 30
Fees  : 5
Ajay
  • 176
  • 6