Java 8 способ работы с перечислением
мне интересно, как лучше всего в Java 8 работать со всеми значениями перечисления. В частности, когда вам нужно получить все значения и добавить его куда - нибудь, например, предположим, что у нас есть следующее перечисление:
public enum Letter {
A, B, C, D;
}
Я мог бы, конечно, сделать следующее:
for (Letter l : Letter.values()) {
foo(l);
}
но, я мог бы также добавить следующий метод определения перечисления:
public static Stream<Letter> stream() {
return Arrays.stream(Letter.values());
}
а затем заменить для сверху с:
Letter.stream().forEach(l -> foo(l));
это подход ОК или у него есть какая-то ошибка в дизайне или производительности? Кроме того, почему перечисления не имеют метода stream ()?
4 ответов:
три вопроса: трехчастный ответ:
это нормально с точки зрения дизайна?
абсолютно. В этом нет ничего плохого. Если вам нужно сделать много итераций над вашим перечислением, stream API-это чистый способ пойти и скрыть котельную плиту за небольшим методом. Хотя я бы рассмотрел OldCumudgeon ' s версия даже лучше.
это нормально с точки зрения производительности?
скорее всего, нет вопрос. В большинстве случаев перечисления не такие большие. Поэтому любые накладные расходы для одного метода или другого, вероятно, не имеют значения в 99,9% случаев.
конечно, есть 0,1%, где он делает. В этом случае: измерьте правильно, с вашими реальными данными и потребителями.
Если бы мне пришлось делать ставки, я бы ожидать
for eachцикл, чтобы быть быстрее, так как он отображает более непосредственно к модели памяти, но не угадайте, когда говорить производительность, и не настраивайте, прежде чем есть актуальная потребность в тюнинге. Напишите свой код таким образом, чтобы он был правильным во-первых, легко читаемым во-вторых, и только потом беспокоиться о производительности стиля кода.Почему перечисления не интегрированы должным образом в API потока?
Если вы сравниваете API потока Java с эквивалентом во многих других языках, он кажется серьезно ограниченным. Существуют различные части, которые отсутствуют (например, многоразовые потоки и опционные потоки). С другой стороны, реализация API потока была конечно, огромные изменения в API. Он был отложен несколько раз по какой-то причине. Поэтому я думаю, что Oracle хотела ограничить изменения самыми важными случаями использования. Перечисления не используются так много в любом случае. Конечно, у каждого проекта есть пара таких, но они ничто по сравнению с количеством списков и других коллекций. Даже когда у вас есть перечисление, во многих случаях вы никогда не будете повторять его. Списки и наборы, с другой стороны, вероятно, повторяются почти каждый раз. Я предполагаю, что это были причины, по которым перечисления не получили свой собственный адаптер в потоковый мир. Мы увидим, будет ли добавлено больше этого в будущих версиях. А до тех пор вы всегда можете использовать
Arrays.stream.
Я бы
EnumSet. Потому чтоforEach()также определена наIterable, вы можете вообще не создавать поток:EnumSet.allOf(Letter.class).forEach(x -> foo(x));или со ссылкой на метод:
EnumSet.allOf(Letter.class).forEach(this::foo);тем не менее, oldschool for-loop чувствует себя немного проще:
for (Letter x : Letter.values()) { foo(x); }
мой Угадай Это перечисления ограничены по размеру (т. е. размер не ограничен языком, но ограничен использованием), и поэтому им не нужно уроженца stream api. Потоки очень хороши, когда вам нужно манипулировать преобразованием и вспоминать элементы в потоке; это не общий случай использования для перечисления (обычно вы повторяете значения перечисления, но редко вам нужно преобразовать, сопоставить и собрать их).
Если вам нужно только сделать действие над каждым элементом возможно, вы должны выставить только метод forEach
public static void forEach(Consumer<Letter> action) { Arrays.stream(Letter.values()).forEach(action); } .... //example of usage Letter.forEach(e->System.out.println(e));
Я думаю, самый короткий код, чтобы получить
Streamперечислимых константStream.of(Letter.values()). Это не так хорошо, какLetter.values().stream()но это проблема с массивами, а не конкретно перечисления.кроме того, почему перечисления не имеют
stream()способ?вы правы, что самый хороший звонок будет
Letter.stream(). К сожалению, класс не может иметь два метода с одной и той же сигнатурой, поэтому было бы невозможно неявно добавить статический методstream()к каждому перечислению (таким же образом, что каждое перечисление имеет неявно добавленный статический методvalues()) поскольку это нарушило бы все существующие перечисления, которые уже имеют статический или экземпляр метода без параметров, называемыхstream().этот подход в порядке?
Я так думаю. Недостатком является то, что
streamявляется статическим методом, поэтому нет никакого способа избежать дублирования кода; он должен быть добавлен к каждому перечислению отдельно.
Comments