Почему перечисления не повторяемы? - PullRequest
64 голосов
/ 26 августа 2008

В 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 под названием ' * 1020 Перечисление *».

Ответы [ 5 ]

80 голосов
/ 05 сентября 2008

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

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

(javax.swing.table.TableColumnModel.getColumns возвращает перечисление.)

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

45 голосов
/ 02 сентября 2008

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

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

Enumeration похоже на Iterator, а не Iterable. A 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. Его можно добавить, не нарушая ничего для циклов, но какой в ​​этом смысл? Если вы можете реализовать этот новый интерфейс Enumerable, почему бы просто не внедрить Iterable вместо этого?

37 голосов
/ 26 августа 2008

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

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

7 голосов
/ 26 августа 2008

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

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

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

2 голосов
/ 02 июля 2015

Если вы хотите, чтобы синтаксически он был немного чище, вы можете использовать:

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