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

Asked
Viewd20150

65

В Java 5 и выше у вас есть цикл foreach, который волшебным образом работает со всем, что реализует Iterable:

 for (Object o : list) {
  doStuff(o);
}
 

Однако Enumerable по-прежнему не реализует Iterable, а это означает, что для перебора Enumeration вы должны сделать следующее:

 for(; e.hasMoreElements() ;) {
  doStuff(e.nextElement());
}
 

Кто-нибудь знает, есть ли причина, по которой Enumeration все еще не реализует Iterable?

Изменить: в качестве пояснения я не говорю о языковой концепции enum , я говорю о классе Java в Java API под названием ' Enumeration '.

5 ответов

40

Перечисление не было изменено для поддержки Iterable, потому что это интерфейс, а не конкретный класс (например, Vector, который был изменен для поддержки интерфейса коллекций).

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

81

В качестве простого и чистого способа использования перечисления с расширенным циклом for преобразование в ArrayList с помощью java.util.Collections.list.

 for (TableColumn col : Collections.list(columnModel.getColumns()) {
 

(javax.swing.table.TableColumnModel.getColumns возвращает Enumeration.)

Обратите внимание, это может быть немного менее эффективно.

7

Перечисление AFAIK вроде "устарело" :

Итератор заменяет Перечисление в коллекциях Java каркас

Я надеюсь, что они изменят API сервлетов с JSR 315, чтобы использовать Iterator вместо Enumeration.

45

Для Enumeration не имеет смысла реализовывать Iterable. Iterable - заводской метод для Iterator. Enumeration аналогичен Iterator и поддерживает состояние только для одного перечисления.

Итак, будьте осторожны, пытаясь обернуть Enumeration как Iterable. Если кто-то передаст мне Iterable, я предполагаю, что могу вызывать iterator() для него несколько раз, создавая столько экземпляров Iterator, сколько хочу, и повторяю каждый независимо друг от друга. Обернутое Enumeration не будет выполнять этот контракт; не позволяйте вашему обернутому Enumeration ускользать из вашего собственного кода. (Кстати, я заметил, что DirectoryStream в Java 7 именно таким образом нарушает ожидания, и ему также нельзя позволить «ускользнуть».)

Enumeration похож на Iterator, а не на Iterable. Collection - это Iterable. Iterator - нет.

Вы не можете этого сделать:

 Vector<X> list = …
Iterator<X> i = list.iterator();
for (X x : i) {
    x.doStuff();
}
 

Так что это было бы бессмысленно:

 Vector<X> list = …
Enumeration<X> i = list.enumeration();
for (X x : i) {
    x.doStuff();
}
 

Не существует Enumerable, эквивалентного Iterable. Его можно было бы добавить, ничего не нарушая для работы циклов for, но в чем будет смысл? Если вы можете реализовать этот новый интерфейс Enumerable, почему бы просто не реализовать вместо него Iterable?