Почему я не могу использовать foreach в перечислении Java? - PullRequest
65 голосов
/ 06 августа 2009

Почему я не могу сделать:

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

Ответы [ 7 ]

59 голосов
/ 06 августа 2009

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

Почему это интересный вопрос? Это не совсем ваш вопрос, но он проливает свет на это. Из FAQ по разработке API Java Collections :

Почему итератор не расширяет перечисление?

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

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

38 голосов
/ 02 марта 2014

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

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

for(Object headerValueObj:headerValuesList){
 ... do whatever you want to do with headerValueObj
}
6 голосов
/ 31 июля 2013

Я решил эту проблему с помощью двух очень простых классов: один для 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)) {
    ...
    }
3 голосов
/ 06 августа 2009

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

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

1 голос
/ 24 мая 2019

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

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

Enumeration e = ...;
Collections.list(e).forEach(o -> {
    ... // use item "o"
});
1 голос
/ 12 июня 2014

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

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

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

for (Object o : Collections.list(e))) {
    ...
}
0 голосов
/ 06 августа 2009

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

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...