Ответ 1
java.util.Collections
имеет метод list
, который копирует Enumeration
в list
, который затем можно использовать в цикле for-each (см. javadoc).
HttpServletRequest использует много java.util.Enumeration. Я хотел бы использовать их в for-each, поэтому мне нужно преобразовать их в interable. это не проблема, но я, так как у меня есть несколько проектов, требующих этого, мне нужна библиотека для этого. Я бы предпочел не создавать свои собственные - есть ли какая-нибудь стандартная библиотека, которая поддерживает этот вид украшения?
Есть ли встроенная конструкция для преобразования Enumeration в Iterable?
java.util.Collections
имеет метод list
, который копирует Enumeration
в list
, который затем можно использовать в цикле for-each (см. javadoc).
Вот 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
. Это не сразу видно при просмотре кода и может быть причиной многих неприятных ошибок. Поэтому я считаю, что имеет смысл не использовать этот метод полезности.
На мой взгляд, документированный путь является самым простым, поэтому нет необходимости преобразовывать в 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());
Взгляните на эту статью: 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();
}
};
}
};
}
}
У вас есть два решения:
Сначала нужно перечислить перечислитель в коллекцию, которая является 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.