Почему я не могу использовать foreach в Java Enumeration?

Почему я не могу:

Enumeration e = ...
for (Object o : e)
  ...

person ripper234    schedule 06.08.2009    source источник
comment
Перечисление было заменено на Iterator в Java 1.2 в 1998 году и оставлено для поддержки устаревших версий. Настоящий вопрос в том, почему вы хотите его использовать. Возможно, потому, что вы используете библиотеку, которая заставляет вас это делать?   -  person Peter Lawrey    schedule 28.08.2010
comment
@Peter - да, внешняя библиотека - это ответ.   -  person ripper234    schedule 30.08.2010


Ответы (8)


Поскольку Enumeration<T> не расширяет _ 2_. Вот пример создания итерируемых перечислений.

Что касается того, почему это интересный вопрос. Это не совсем ваш вопрос, но он проливает на него свет. Из часто задаваемых вопросов по дизайну API коллекций Java:

Почему Iterator не расширяет Enumeration?

Мы считаем имена методов для Enumeration неудачными. Они очень длинные и используются очень часто. Учитывая, что мы добавляли метод и создавали совершенно новую структуру, мы чувствовали, что было бы глупо не воспользоваться возможностью улучшить имена. Конечно, мы могли бы поддерживать новые и старые имена в Iterator, но это не имеет смысла.

Это в основном подсказывает мне, что Sun хочет дистанцироваться от Enumeration, который является очень ранней версией Java с довольно подробным синтаксисом.

person cletus    schedule 06.08.2009
comment
Следующий вопрос: почему перечисления не являются итерируемыми? stackoverflow.com/questions/27240/ - person Michael Myers; 06.08.2009
comment
Есть ли между ними семантическая разница? (Я не знаком с классом Iterable)? Почему бы не поработать и над Enumeration? - person ripper234; 06.08.2009
comment
Поскольку перечисления больше похожи на Iterator, а не на Iterable (см. Опубликованный mmyers вопрос о stackoverflow). В качестве обходного пути вы можете сделать for(; e.hasMoreElements(); ) { e.getNextElement(); } - person Tim; 06.08.2009
comment
Но Iterators тоже не Iterable. Вы не можете сделать for (obj : itr). Причина этого в том, что Iterable действительно повторяется многократно, тогда как итератор может повторяться только один раз. - person oxbow_lakes; 06.08.2009
comment
Вы имеете в виду, что Enumeration ‹T› не реализует итеративно ‹T› вместо расширения? - person Jimmy; 26.08.2010
comment
Это не объясняет, почему Sun / Oracle не разрешили Enumeration в новом синтаксисе for, а также Iterable и array. - person mjaggard; 02.04.2013
comment
здесь - это однострочное исправление для использования перечисления в расширенном цикле for (foreach) - person David Balažic; 29.04.2019

Используя служебный класс Collections, Enumeration можно сделать повторяющимся, например:

Enumeration headerValues=request.getHeaders("mycustomheader");
List headerValuesList=Collections.list(headerValues);

for(Object headerValueObj:headerValuesList){
 ... do whatever you want to do with headerValueObj
}
person user1555669    schedule 02.03.2014
comment
Элементы копируются в новый список перед началом итерации, этого решения следует избегать для длинных перечислений. Решения, превращающие Enumeration в Iterator, имеют меньше накладных расходов на память. - person Emmanuel Bourg; 18.12.2014
comment
@EmmanuelBourg, но у них есть побочные эффекты, поскольку перечисления сохраняют состояние. - person P.Péter; 17.03.2016
comment
Это, безусловно, самый простой ответ! Никаких зависимостей не требуется и легко читается. Спасибо! - person Geert Schuring; 30.03.2016

Я решил эту проблему с помощью двух очень простых классов: для Enumeration и для Iterator. Оболочка перечисления выглядит следующим образом:

static class IterableEnumeration<T>
extends Object
implements Iterable<T>, Iterator<T>
{
private final Enumeration<T>        enumeration;
private boolean                     used=false;

IterableEnumeration(final Enumeration<T> enm) {
    enumeration=enm;
    }

public Iterator<T> iterator() {
    if(used) { throw new IllegalStateException("Cannot use iterator from asIterable wrapper more than once"); }
    used=true;
    return this;
    }

public boolean hasNext() { return enumeration.hasMoreElements(); }
public T       next()    { return enumeration.nextElement();     }
public void    remove()  { throw new UnsupportedOperationException("Cannot remove elements from AsIterator wrapper around Enumeration"); }
}

Что можно использовать либо со статическим служебным методом (что я предпочитаю):

/**
 * Convert an `Enumeration<T>` to an `Iterable<T>` for a once-off use in an enhanced for loop.
 */
static public <T> Iterable<T> asIterable(final Enumeration<T> enm) {
    return new IterableEnumeration<T>(enm);
    }

...

for(String val: Util.asIterable(enm)) {
    ...
    }

или создав экземпляр класса:

for(String val: new IterableEnumeration<String>(enm)) {
    ...
    }
person Lawrence Dol    schedule 31.07.2013

Новый стиль цикла («foreach») работает с массивами и вещами, реализующими интерфейс Iterable.

Он также более похож на Iterator, чем на Iterable, поэтому Enumeration не имеет смысла работать с foreach, если Iterator тоже не работает (а это не так). Enumeration также не рекомендуется в пользу Iterator.

person Laurence Gonsalves    schedule 06.08.2009
comment
Будем осторожны с терминами здесь. При обсуждении API-интерфейсов отказ от поддержки означает нечто очень конкретное. Использование Enumeration не рекомендуется, но оно не устарело. - person ykaganovich; 06.08.2009
comment
Ыкаганович: хорошее замечание. Я исправил текст в ответе. - person Laurence Gonsalves; 06.08.2009

С java 8 и выше это возможно:

import java.util.Collections;
import java.util.Enumeration;

Enumeration e = ...;
Collections.list(e).forEach(o -> {
    ... // use item "o"
});
person slartidan    schedule 24.05.2019

Enumeration не реализует Iterable и поэтому не может использоваться непосредственно в цикле foreach. Однако, используя коллекции Apache Commons, можно перебирать перечисление с помощью:

for (Object o : new IteratorIterable(new EnumerationIterator(e))) {
    ...
}

Вы также можете использовать более короткий синтаксис с Collections.list(), но это менее эффективно (две итерации по элементам и большее использование памяти):

for (Object o : Collections.list(e))) {
    ...
}
person Emmanuel Bourg    schedule 12.06.2014
comment
вы имеете в виду IteratorIterable? - person luckyluke; 05.11.2016

Поскольку Enumeration (и большинство классов, производных от этого интерфейса) не реализует Iterable.

Вы можете попробовать написать свой собственный класс-оболочку.

person Stroboskop    schedule 06.08.2009
comment
Вам не следует писать оболочку для Enumeration, которая превращает его в Iterable, точно так же, как вы должны создавать такую ​​оболочку для Iterator. Объекты Iterator и Enumeration сохраняют состояние по отношению к итерации. Итерируемые объекты - нет. - person Laurence Gonsalves; 06.08.2009

Мы можем использовать цикл for для перебора перечисления, используя .values​​()

method which returns all the elements contained in the enumeration.

Пример :

for (USERS_ROLES userRole: USERS_ROLES .values ​​()) {
            System.out.println ("This is one user role:" + userRole.toString ());
}

Я сделал это в java 10

person Amede Angel Aulerien    schedule 29.07.2020