Generic Перечисление в Iterable конвертер

HttpServletRequest использует много java.util.Enumeration. Я хотел бы использовать их в for-each, поэтому мне нужно преобразовать их в interable. это не проблема, но я, так как у меня есть несколько проектов, требующих этого, мне нужна библиотека для этого. Я бы предпочел не создавать свои собственные - есть ли какая-нибудь стандартная библиотека, которая поддерживает этот вид украшения?

Есть ли встроенная конструкция для преобразования Enumeration в Iterable?

Ответ 1

java.util.Collections имеет метод list, который копирует Enumeration в list, который затем можно использовать в цикле for-each (см. javadoc).

Ответ 2

Вот javadoc из Guava относительно преобразования перечисления в Iterator (не повторяется):

public static UnmodifiableIterator forEnumeration (перечисление перечислений)

Адаптирует перечисление к интерфейсу Iterator.

Этот метод не имеет эквивалента в Iterables, потому что просмотр Перечисление как Iterable невозможно. Однако содержимое может быть скопированы в коллекцию, используя Collections.list(java.util.Enumeration).

Дальнейшая реализация новых коллекций apache commons не поддерживает функции Java 5 и API, такие как Iterable, поэтому нет никаких шансов.

Однако есть те же методы в тех библиотеках, которые позволяют вам перечислить перечисление в итерабельную коллекцию и использовать ее (они неявно копируют ваши данные).

Например, преобразование в список с помощью EnumerationUtils.toList(перечисление).

Изменить: из-за некоторых вопросов в вопросе, я попытаюсь подвести итог, почему создатели guava (и я) не чувствуют, что перечисление может быть сделано в итерируемый.

Итерируемый создает экземпляры итератора, кто-то, читающий код (или API), может предположить, что каждый вызов iterator() дает новый экземпляр итератора, начинающий перечисление с первого элемента. Если мы сделаем простое преобразование между итератором (или перечислением) и итерабельным, тогда пользователь API должен знать, что вызов iterator() изменяет состояние объекта и что два последовательных вызова могут вести себя странно. вот пример:

Iterable<String> iter = magicFunction(enumeration);
for (String s : iter) {
  if ("hello".equals(s))
    break;
}

for (String s : iter) {
  if ("world".equals(s))
    return true;
}
return false;

Если реализовано как простое преобразование (O (1)). Вышеуказанный метод ведет себя по-разному для разных входов: ["hello","world"] вернет true, а ["world","hello"] вернет false. Это не сразу видно при просмотре кода и может быть причиной многих неприятных ошибок. Поэтому я считаю, что имеет смысл не использовать этот метод полезности.

Ответ 3

На мой взгляд, документированный путь является самым простым, поэтому нет необходимости преобразовывать в Iterator:

https://docs.oracle.com/javase/1.5.0/docs/api/java/util/Enumeration.html

for (Enumeration<E> e = v.elements(); e.hasMoreElements();)
   System.out.println(e.nextElement());

Ответ 4

Взгляните на эту статью: http://www.java2s.com/Code/Java/Collections-Data-Structure/TreatanEnumerationasanIterable.htm

Кажется, именно то, что вам нужно.

ОБНОВЛЕНО Добавлен код для дальнейшего использования в случае нарушения связи.

import java.util.Enumeration;
import java.util.Iterator;

/**
 * @since 4.37
 * @author Jaroslav Tulach
 */
public class Utils {
  public static <E> Iterable<E> iterable(final Enumeration<E> enumeration) {
      if (enumeration == null) {
          throw new NullPointerException();
      }
      return new Iterable<E>() {
          public Iterator<E> iterator() {
              return new Iterator<E>() {
                  public boolean hasNext() {
                      return enumeration.hasMoreElements();
                  }
                  public E next() {
                      return enumeration.nextElement();
                  }
                  public void remove() {
                      throw new UnsupportedOperationException();
                  }
              };
          }
      };
  }    
}

Ответ 5

У вас есть два решения:

Сначала нужно перечислить перечислитель в коллекцию, которая является Iterable (как описано @skaffman). Это добавит O (n), как отмечено @Michael

В случаях, когда у вас есть доступ к методу, который создал перечислитель, вы можете обернуть его в Iterable, не оплачивая расходы. В вашем случае вы можете создать Iterable с помощью:

final Request request2 = request;
Iterable<String> headerNamesIterable = new Iterable<String>(){
    public Iterator<T>  iterator(){
      return Iterators.forEnumeration(request2.getHeaderNames())
    }
}
Iterable<String> headersIterableName1 = new Iterable<String>(){
    public Iterator<T>  iterator(){
      return Iterators.forEnumeration(request2.getHeaders("name1"))
    }
}

В этом случае вы можете многократно повторять итераторы, созданные объектами Iterable.