Повторите перечисление в Java 8



можно ли повторить Enumeration С помощью лямбда-выражения? Каким будет лямбда-представление следующего фрагмента кода:



Enumeration<NetworkInterface> nets = NetworkInterface.getNetworkInterfaces();

while (nets.hasMoreElements()) {
NetworkInterface networkInterface = nets.nextElement();

}


Я не нашел в нем никакого потока.

733   7  

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.2
  • Iterators.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

    Ничего не найдено.