Цикл for для перебора перечисления в Java

У меня есть enum на Java для основных и промежуточных направлений:

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

Как я могу написать for цикл, который перебирает каждое из этих enum значений?


person Nick Meyer    schedule 09.07.2009    source источник
comment
Java 8: stackoverflow.com/a/30962181/1216775   -  person akhil_mittal    schedule 21.09.2018


Ответы (10)


.values()

Вы можете вызвать метод values() в своем перечислении.

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

Этот values() метод неявно объявлен компилятор. Поэтому его нет в Enum doc.

person notnoop    schedule 09.07.2009
comment
Почему этот метод values ​​() не указан здесь в java.lang.enum - person jacktrades; 17.01.2013
comment
@jacktrades: это неявный метод, который существует только в компиляторе. Поэтому базовый класс не может объявить метод с тем же именем и, следовательно, не будет включен в автоматически сгенерированную документацию Javadocs. docs.oracle.com/ javase / specs / jls / se7 / html / jls-8.html # jls-8.9.2 - person Torben; 05.03.2013
comment
Как ни странно, он упоминается в valueOf () docs - person greg7gkb; 04.09.2017

Все константы перечисляемого типа можно получить, вызвав неявный метод public static T[] values() этого типа:

 for (Direction d : Direction.values()) {
     System.out.println(d);
 }
person dfa    schedule 09.07.2009
comment
@ RAnders00 Верно. Но все же ответ верен, и формат действительно не имеет значения (по крайней мере, для меня) - person dARKpRINCE; 08.02.2016
comment
Что делает #? - person YoTengoUnLCD; 11.06.2016
comment
@YoTengoUnLCD В основном это говорит о том, что values ​​() является частью объекта Enum. например, Enum#values() = Enum.values() - person Spotlight; 12.06.2016
comment
Хм, извините, я не понимаю, это то же самое, что использовать . (всегда?)? - person YoTengoUnLCD; 12.06.2016
comment
@YoTengoUnLCD Хэштег - это синтаксис JavaDoc, а не код Java. - person Jeff G; 31.10.2016

Сделать это можно следующим образом:

for (Direction direction : EnumSet.allOf(Direction.class)) {
  // do stuff
}
person toluju    schedule 09.07.2009
comment
Если вы импортируете java.util.EnumSet - person Nate; 09.07.2009
comment
Очень полезно для циклов foreach в Java8. EnumSet.allOf (Enum.class) .forEach (бла - ›метод (бла)) - person Hiro2k; 02.06.2015
comment
@ Hiro2k Еще можно было сделать Arrays.stream(Enum.values()).forEach(...) - поток будет последовательным - person RAnders00; 08.02.2016
comment
Вы можете объяснить, почему это лучше, чем Enum.values()? - person schatten; 14.05.2016
comment
@schatten ну, это set вместо array. Это не лучше, хотя, на мой взгляд, он лучше описывает значения перечисления, потому что из определения набора значения в наборе не могут повторяться (как в перечислении), тогда как значения в массиве могут быть. - person Jezor; 08.09.2016
comment
@Jezor Это лучший выбор, когда вам действительно нужен очень быстрый набор перечислений, таких как битовые флаги, хотя он кажется слишком сложным для простой итерации. - person schatten; 08.09.2016

Потоки

До Java 8

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

Java 8

Мы также можем использовать лямбда-выражения и потоки (Учебное пособие):

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

Почему forEachOrdered, а не forEach с потоками?

Поведение forEach явно недетерминировано, поскольку forEachOrdered выполняет действие для каждого элемента этого потока в порядке встречи потока, если поток имеет определенный порядок встречи. Таким образом, forEach не гарантирует, что порядок будет сохранен.

Также при работе с потоками (особенно параллельными) помните о природе потоков. Согласно doc:

Результаты потокового конвейера могут быть недетерминированными или неверными, если поведенческие параметры потоковых операций имеют состояние. Лямбда с отслеживанием состояния - это лямбда, результат которой зависит от любого состояния, которое может измениться во время выполнения потокового конвейера.

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

Здесь, если операция сопоставления выполняется параллельно, результаты для одного и того же ввода могут варьироваться от запуска к запуску из-за различий в планировании потоков, тогда как с лямбда-выражением без сохранения состояния результаты всегда будут одинаковыми.

Побочные эффекты в поведенческих параметрах потоковых операций, как правило, не приветствуются, поскольку они часто могут привести к невольным нарушениям требования безгражданства, а также к другим угрозам безопасности потоков.

Потоки могут иметь или не иметь определенный порядок встречи. Имеет ли поток порядок встречи или нет, зависит от источника и промежуточных операций.

person akhil_mittal    schedule 21.06.2015
comment
Как и во всех потоковых операциях, помните об отсутствии состояния потока и ограничениях побочных эффектов docs.oracle.com/javase/8/docs/api/java/util/stream/. Эти 2 варианта итерации перечисления существенно различаются в этом отношении. - person buzz3791; 05.12.2018

Если вас не волнует порядок, это должно сработать:

Set<Direction> directions = EnumSet.allOf(Direction.class);
for(Direction direction : directions) {
    // do stuff
}
person Tom Jefferys    schedule 09.07.2009
comment
Если вы импортируете java.util.EnumSet и java.util.Set - person Nate; 09.07.2009
comment
Из документации для EnumSet: Итератор, возвращаемый методом итератора, обходит элементы в их естественном порядке (порядке, в котором объявлены константы перечисления). Это гарантирует, что порядок итерации соответствует порядку, возвращаемому Enum.values(). - person Jeff G; 31.10.2016

Java8

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

из Java5 +

for ( Direction d: Direction.values()){
 System.out.println(d);
}
person Raghu K Nair    schedule 25.02.2016
comment
ой, извини. Я только что понял, что akhil_mittal уже публиковал аналогичный ответ. - person Raghu K Nair; 25.02.2016
comment
Когда и почему мне следует использовать Stream.of (o) .forEach? Цикл for кажется более читаемым. - person Jeremy; 03.05.2016
comment
Нет, если вы знакомы с функциональным программированием. - person Alexis Dufrenoy; 14.12.2016

Попробуйте использовать для каждого

for ( Direction direction : Direction.values()){
  System.out.println(direction.toString());
}
person Irazza    schedule 23.06.2016

Другие методы в java 8:

Использование EnumSet с forEach

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

Использование Arrays.asList с forEach

Arrays.asList(Direction.values()).forEach(...);
person NiVeR    schedule 23.05.2018

мы можем использовать такой фильтр (JAVA 8).

Stream.of(Direction.values()).filter(name -> !name.toString().startsWith("S")).forEach(System.out::println);
person Sarat Kumar    schedule 16.08.2020

values ​​() может просто работать:

for (Direction  d : Direction.values()) {
   //whatever you want to do with each of these enum values  
}
person nabayram    schedule 26.01.2021
comment
Ваш ответ такой же, как здесь: stackoverflow.com/a/1104994/11876201, попробуйте, пожалуйста, объясните больше, чтобы сделать Ваш ответ более полезен - person phoenixstudio; 26.01.2021