Повторите перечисление в Java 8
можно ли повторить Enumeration С помощью лямбда-выражения? Каким будет лямбда-представление следующего фрагмента кода:
Enumeration<NetworkInterface> nets = NetworkInterface.getNetworkInterfaces();
while (nets.hasMoreElements()) {
NetworkInterface networkInterface = nets.nextElement();
}
Я не нашел в нем никакого потока.
7 ответов:
в случае, если вам не нравится тот факт, что
Collections.list(Enumeration)копирует все содержимое в (Временный) список до начала итерации, вы можете помочь себе с помощью простого метода:public static <T> void forEachRemaining(Enumeration<T> e, Consumer<? super T> c) { while(e.hasMoreElements()) c.accept(e.nextElement()); }затем вы можете просто сделать
forEachRemaining(enumeration, lambda-expression);(обратите внимание наimport staticхарактеристика)...
(этот ответ показывает один из многих вариантов. Просто потому, что это
ибыл знак принятия, не означает, что это лучший. Я предлагаю прочитать другие ответы и выбрать один в зависимости от ситуации, в которой вы находитесь. Лично для Java 8 я нахожу ответ Хольгера самое приятное, потому что это также просто, но не требует дополнительной итерации - что происходит в моем решении. Но для решения Java 9 посетите Тагир Валеев ответ)
вы можете копировать элементы из своего
EnumerationдоArrayListСCollections.listи затем использовать его какCollections.list(yourEnumeration).forEach(yourAction);
если их много перечисления в коде, я рекомендую создать статический вспомогательный метод, который преобразует перечисление на поток. Статический метод может выглядеть следующим образом:
public static <T> Stream<T> enumerationAsStream(Enumeration<T> e) { return StreamSupport.stream( Spliterators.spliteratorUnknownSize( new Iterator<T>() { public T next() { return e.nextElement(); } public boolean hasNext() { return e.hasMoreElements(); } }, Spliterator.ORDERED), false); }используйте метод с статический импорт. В отличие от решения Хольгера, вы можете извлечь выгоду из различных поток операции, которые могут сделать существующий код еще проще. Вот пример:
Map<...> map = enumerationAsStream(enumeration) .filter(Objects::nonNull) .collect(groupingBy(...));
С Java-9 появится новый метод по умолчанию
Enumeration.asIterator()что сделает чистое решение Java проще:nets.asIterator().forEachRemaining(iface -> { ... });
вы можете использовать следующую комбинацию стандартных функций:
StreamSupport.stream(Spliterators.spliteratorUnknownSize(CollectionUtils.toIterator(enumeration), Spliterator.IMMUTABLE), parallel)вы также можете добавить больше характеристик, таких как
NONNULLилиDISTINCT.после применения статического импорта это станет более читаемым:
stream(spliteratorUnknownSize(toIterator(enumeration), IMMUTABLE), false)теперь у вас есть стандартный поток Java 8, который будет использоваться в любом случае! Вы можете пройти
trueдля параллельной обработки.для преобразования из перечисления в итератор используйте любой из:
CollectionUtils.toIterator()С весны 3.2 или вы можете использоватьIteratorUtils.asIterator()из коллекции Apache Commons 3.2Iterators.forEnumeration()от Google Guava
для Java 8 самым простым преобразованием перечисления в поток является:
Collections.list(NetworkInterface.getNetworkInterfaces()).stream()
Я знаю, что это старый вопрос, но я хотел представить альтернативу коллекциям.asList и функции потока. Поскольку вопрос называется "итерация перечисления", я признаю, что иногда вы хотите использовать лямбда-выражение, но расширенный цикл for может быть предпочтительным, поскольку перечисляемый объект может вызывать исключение, а цикл for легче инкапсулировать в более крупный сегмент кода try-catch (лямбды требуют, чтобы объявленные исключения были пойманы в лямбде). С этой целью, здесь использует лямбда для создания итерируемого, который можно использовать в цикле for и не загружает перечисление:
/** * Creates lazy Iterable for Enumeration * * @param <T> Class being iterated * @param e Enumeration as base for Iterator * @return Iterable wrapping Enumeration */ public static <T> Iterable<T> enumerationIterable(Enumeration<T> e) { return () -> new Iterator<T>() { @Override public T next() { return e.nextElement(); } @Override public boolean hasNext() { return e.hasMoreElements(); } }; }
Comments