Die Aufzählung wurde 1998 in Java 1.2 durch Iterator ersetzt und wird für die Unterstützung älterer Versionen beibehalten. Die eigentliche Frage ist, warum Sie es verwenden möchten. Möglicherweise, weil Sie eine Bibliothek verwenden, die Sie dazu zwingt?
Peter Lawrey
2
@ Peter - ja, eine externe Bibliothek ist die Antwort.
Warum ist das eine interessante Frage? Dies ist nicht gerade Ihre Frage, aber sie wirft ein Licht darauf. Aus den häufig gestellten Fragen zum Java Collections API Design :
Warum erweitert Iterator die Aufzählung nicht?
Wir betrachten die Methodennamen für die Aufzählung als unglücklich. Sie sind sehr lang und werden sehr häufig verwendet. Angesichts der Tatsache, dass wir eine Methode hinzugefügt und ein völlig neues Framework erstellt haben, hielten wir es für dumm, die Gelegenheit zur Verbesserung der Namen nicht zu nutzen. Natürlich könnten wir die neuen und alten Namen in Iterator unterstützen, aber es scheint sich nicht zu lohnen.
Das legt mir im Grunde nahe, dass Sun sich von Enumeration distanzieren möchte, einem sehr frühen Java mit einer ziemlich ausführlichen Syntax.
Gibt es einen semantischen Unterschied zwischen den beiden? (Ich bin nicht mit der Iterable-Klasse vertraut)? Warum nicht auch an der Aufzählung arbeiten?
Ripper234
4
Da Aufzählungen eher Iterator als Iterable ähneln (siehe die gestellte Frage zum Stapelüberlauf mmyers). Als Workaround können Sie tunfor(; e.hasMoreElements(); ) { e.getNextElement(); }
Tim
4
Aber Iteratorsauch nicht Iterable. Das kannst du nicht machen for (obj : itr). Der Grund dafür ist, dass Iterablees wirklich wiederholt iterierbar ist , während ein Iterator nur einmal iteriert werden kann.
oxbow_lakes
4
Dies erklärt nicht, warum Sun / Oracle ein Enumerationin der neuen forSyntax sowie ein Iterableund ein nicht zugelassen hat array.
mjaggard
45
Mit der Dienstprogrammklasse "Sammlungen" kann die Aufzählung wie folgt iterierbar gemacht werden:
Enumeration headerValues=request.getHeaders("mycustomheader");
List headerValuesList=Collections.list(headerValues);
for(Object headerValueObj:headerValuesList){
... do whatever you want to do with headerValueObj
}
Die Elemente werden vor Beginn der Iteration in eine neue Liste kopiert. Diese Lösung sollte bei langen Aufzählungen vermieden werden. Die Lösungen, die eine Aufzählung in einen Iterator verwandeln, haben weniger Speicheraufwand.
Emmanuel Bourg
@EmmanuelBourg, aber sie haben Nebenwirkungen, da Aufzählungen zustandsbehaftet sind.
P.Péter
1
Dies ist bei weitem die einfachste Antwort! Keine Abhängigkeiten erforderlich und klar lesbar. Vielen Dank!
Geert Schuring
7
Ich habe dieses Problem mit zwei sehr einfachen Klassen gelöst, einer für Enumerationund einer für Iterator. Der Aufzählungs-Wrapper lautet wie folgt:
staticclassIterableEnumeration<T>
extendsObjectimplementsIterable<T>, Iterator<T>
{
privatefinal Enumeration<T> enumeration;
privateboolean used=false;
IterableEnumeration(final Enumeration<T> enm) {
enumeration=enm;
}
public Iterator<T> iterator(){
if(used) { thrownew IllegalStateException("Cannot use iterator from asIterable wrapper more than once"); }
used=true;
returnthis;
}
publicbooleanhasNext(){ return enumeration.hasMoreElements(); }
public T next(){ return enumeration.nextElement(); }
publicvoidremove(){ thrownew UnsupportedOperationException("Cannot remove elements from AsIterator wrapper around Enumeration"); }
}
Welche kann entweder mit einer statischen Dienstprogrammmethode verwendet werden (was meine Präferenz ist):
/**
* Convert an `Enumeration<T>` to an `Iterable<T>` for a once-off use in an enhanced for loop.
*/staticpublic <T> Iterable<T> asIterable(final Enumeration<T> enm){
returnnew IterableEnumeration<T>(enm);
}
...
for(String val: Util.asIterable(enm)) {
...
}
oder durch Instanziieren der Klasse:
for(String val: new IterableEnumeration<String>(enm)) {
...
}
Der New-Style-for-Loop ("foreach") funktioniert für Arrays und Dinge, die das implementieren Iterable Schnittstelle .
Es ist auch analoger Iteratorals zu Iterable, daher wäre es nicht sinnvoll Enumeration, mit foreach zu arbeiten, wenn es Iteratornicht auch so wäre (und es tut es nicht).
Enumerationwird auch zugunsten von entmutigt Iterator.
Seien wir vorsichtig mit den Begriffen hier. Verfall bedeutet etwas sehr Spezifisches bei der Diskussion von APIs. Von der Verwendung der Aufzählung wird abgeraten, sie wird jedoch nicht veraltet.
Ykaganovich
Ykaganovich: Guter Punkt. Ich habe den Text in der Antwort korrigiert.
Laurence Gonsalves
2
Mit Java 8 und darüber hinaus ist dies möglich:
import java.util.Collections;
import java.util.Enumeration;
Enumeration e = ...;
Collections.list(e).forEach(o -> {
... // use item "o"
});
Enumerationwird nicht implementiert Iterableund kann daher nicht direkt in einer foreach-Schleife verwendet werden. Mit Apache Commons Collections ist es jedoch möglich, eine Aufzählung mit folgenden Elementen zu durchlaufen:
for (Object o : new IteratorIterable(new EnumerationIterator(e))) {
...
}
Sie können auch eine kürzere Syntax verwenden Collections.list(), dies ist jedoch weniger effizient (zwei Iterationen über die Elemente und mehr Speichernutzung):
Sie sollten keinen Wrapper für Enumeration schreiben, der ihn zu einem Iterable macht, genauso wenig wie Sie einen solchen Wrapper für Iterator erstellen sollten. Iterator- und Aufzählungsobjekte sind in Bezug auf die Iteration zustandsbehaftet. Iterables sind nicht.
Laurence Gonsalves
0
Wir können die for-Schleife verwenden, um eine Aufzählung mit der zu durchlaufen .values()
methodwhich returns all the elements contained in the enumeration.
Ein Beispiel :
for (USERS_ROLES userRole: USERS_ROLES .values ()) {
System.out.println ("This is one user role:" + userRole.toString ());
}
Antworten:
Weil
Enumeration<T>
nicht verlängertIterable<T>
. Hier ist ein Beispiel für die Erstellung iterierbarer Aufzählungen .Warum ist das eine interessante Frage? Dies ist nicht gerade Ihre Frage, aber sie wirft ein Licht darauf. Aus den häufig gestellten Fragen zum Java Collections API Design :
Das legt mir im Grunde nahe, dass Sun sich von Enumeration distanzieren möchte, einem sehr frühen Java mit einer ziemlich ausführlichen Syntax.
quelle
for(; e.hasMoreElements(); ) { e.getNextElement(); }
Iterators
auch nichtIterable
. Das kannst du nicht machenfor (obj : itr)
. Der Grund dafür ist, dassIterable
es wirklich wiederholt iterierbar ist , während ein Iterator nur einmal iteriert werden kann.Enumeration
in der neuenfor
Syntax sowie einIterable
und ein nicht zugelassen hatarray
.Mit der Dienstprogrammklasse "Sammlungen" kann die Aufzählung wie folgt iterierbar gemacht werden:
Enumeration headerValues=request.getHeaders("mycustomheader"); List headerValuesList=Collections.list(headerValues); for(Object headerValueObj:headerValuesList){ ... do whatever you want to do with headerValueObj }
quelle
Ich habe dieses Problem mit zwei sehr einfachen Klassen gelöst, einer für
Enumeration
und einer fürIterator
. Der Aufzählungs-Wrapper lautet wie folgt: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"); } }
Welche kann entweder mit einer statischen Dienstprogrammmethode verwendet werden (was meine Präferenz ist):
/** * 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)) { ... }
oder durch Instanziieren der Klasse:
for(String val: new IterableEnumeration<String>(enm)) { ... }
quelle
Der New-Style-for-Loop ("foreach") funktioniert für Arrays und Dinge, die das implementieren
Iterable
Schnittstelle .Es ist auch analoger
Iterator
als zuIterable
, daher wäre es nicht sinnvollEnumeration
, mit foreach zu arbeiten, wenn esIterator
nicht auch so wäre (und es tut es nicht).Enumeration
wird auch zugunsten von entmutigtIterator
.quelle
Mit Java 8 und darüber hinaus ist dies möglich:
import java.util.Collections; import java.util.Enumeration; Enumeration e = ...; Collections.list(e).forEach(o -> { ... // use item "o" });
quelle
Enumeration
wird nicht implementiertIterable
und kann daher nicht direkt in einer foreach-Schleife verwendet werden. Mit Apache Commons Collections ist es jedoch möglich, eine Aufzählung mit folgenden Elementen zu durchlaufen:for (Object o : new IteratorIterable(new EnumerationIterator(e))) { ... }
Sie können auch eine kürzere Syntax verwenden
Collections.list()
, dies ist jedoch weniger effizient (zwei Iterationen über die Elemente und mehr Speichernutzung):for (Object o : Collections.list(e))) { ... }
quelle
Da eine Aufzählung (und die meisten von dieser Schnittstelle abgeleiteten Klassen) Iterable nicht implementiert.
Sie können versuchen, Ihre eigene Wrapper-Klasse zu schreiben.
quelle
Wir können die for-Schleife verwenden, um eine Aufzählung mit der zu durchlaufen
.values()
method
which returns all the elements contained in the enumeration.
Ein Beispiel :
for (USERS_ROLES userRole: USERS_ROLES .values ()) { System.out.println ("This is one user role:" + userRole.toString ()); }
Ich habe es in Java 10 gemacht
quelle