Цикл "для", щоб повторити перерахунок на Java


876

У мене є enumJava для кардинальних та проміжних напрямків:

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

Як я можу написати forцикл, який повторюється через кожне з цих enumзначень?


Відповіді:


1400

.values()

Ви можете зателефонувати за values()методом на перерахунок.

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

Цей values()метод неявно оголошується компілятором . Тож це не вказано на Enumdoc.


43
Чому значення цього методу () не вказані тут під java.lang.enum
jacktrades

80
@jacktrades: Це неявний метод, який існує лише в компіляторі. Тому базовий клас не може оголосити метод з тим самим іменем і, таким чином, він не включається в автоматично створені Javadocs. docs.oracle.com/javase/specs/jls/se7/html/jls-8.html#jls-8.9.2
Torben

4
Як не дивно, він згадується у значенні valueOf () docs
greg7gkb

129

Усі константи типу enum можна отримати, викликавши неявний public static T[] values()метод цього типу:

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

@ RAnders00 Правда. Але все ж відповідь справедлива, і формат насправді не має значення (принаймні для мене)
dARKpRINCE

Що робить #?
YoTengoUnLCD

@YoTengoUnLCD В основному це говорить про те, що значення () є частиною об'єкта Enum. напр. Enum#values()=Enum.values()
Прожектор

Хм, вибачте, я не дотримуюся, це те саме, що використовувати .(завжди?)?
YoTengoUnLCD

3
@YoTengoUnLCD Хештег - це синтаксис JavaDoc, а не код Java.
Джефф G

62

Це можна зробити так:

for (Direction direction : EnumSet.allOf(Direction.class)) {
  // do stuff
}

1
За умови, що ви імпортуєте java.util.EnumSet
Nate

8
Супер корисний для циклів foreach Java8. EnumSet.allOf (Enum.class) .forEach (blah -> метод (blah))
Hiro2k

1
@ Hiro2k Ви також можете зробити Arrays.stream(Enum.values()).forEach(...)- потік буде послідовним
RAnders00

1
@schatten добре, це setзамість array. Це не "краще", хоча воно, на мою думку, описує значення перерахунків, тому що з визначення множини значення в наборі не можна повторити (як у перерахунку), тоді як значення в масиві можуть бути.
Jezor

2
@Jezor Це кращий вибір, коли вам насправді потрібен дуже швидкий набір переліків, як бітові прапори, хоча це здається занадто складним для простої ітерації.
schatten

44

Потоки

До 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не гарантує, що порядок буде дотримано.

Також при роботі з потоками (особливо паралельними) пам’ятайте про природу потоків. Відповідно до документа :

Результати потокового конвеєра можуть бути недетермінованими або неправильними, якщо параметри поведінки для операцій потоку є стаціонарними. Влучна лямбда - результат, результат якого залежить від стану, який може змінитися під час виконання потокового конвеєра.

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

Тут, якщо операція з картографуванням виконується паралельно, результати одного і того ж вводу можуть змінюватись від запуску до запуску через різниці в плануванні потоку, тоді як, за виразом лямбда без стану, результати завжди будуть однаковими.

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

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


Як і у всіх операціях потоку, слід пам’ятати про обмеження стану стану потоку та обмеження побічних ефектів docs.oracle.com/javase/8/docs/api/java/util/stream/… . Ці два варіанти ітерації перерахунків суттєво відрізняються в цьому плані.
buzz3791


19

Якщо ви не дбаєте про замовлення, це повинно працювати:

Set<Direction> directions = EnumSet.allOf(Direction.class);
for(Direction direction : directions) {
    // do stuff
}

2
За умови імпорту java.util.EnumSet і java.util.Set
Nate

4
З документації дляEnumSet : Ітератор, що повертається методом ітератора, переміщує елементи в їх природному порядку (порядку, в якому оголошуються константи перерахунку) . Це гарантує, що порядок ітерації відповідає порядку, поверненому Enum.values().
Джефф G


5

Java8

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

від Java5 +

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

1
Ой, вибачте. Я щойно зрозумів, що аналогічну відповідь вже розмістив akhil_mittal.
Raghu K Nair

Коли і чому я повинен використовувати Stream.of (o) .forEach? Цикл for здається набагато читабельнішим.
Джеремі

Не, якщо ви знайомі з функціональним програмуванням.
Олексій Дуфрой

5

Спробуйте використовувати для кожного

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

4

Більше методів у java 8:

Використання EnumSetсforEach

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

Використання Arrays.asListсforEach

Arrays.asList(Direction.values()).forEach(...);
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.