Warum kann ich nicht tun:
Enumeration e = ...
for (Object o : e)
...
Warum kann ich nicht tun:
Enumeration e = ...
for (Object o : e)
...
Antworten:
Weil Enumeration<T>
nicht verlängert Iterable<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 :
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.
for(; e.hasMoreElements(); ) { e.getNextElement(); }
Iterators
auch nicht Iterable
. Das kannst du nicht machen for (obj : itr)
. Der Grund dafür ist, dass Iterable
es wirklich wiederholt iterierbar ist , während ein Iterator nur einmal iteriert werden kann.
Enumeration
in der neuen for
Syntax sowie ein Iterable
und ein nicht zugelassen hat array
.
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
}
Ich habe dieses Problem mit zwei sehr einfachen Klassen gelöst, einer für Enumeration
und einer für Iterator
. 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)) {
...
}
Der New-Style-for-Loop ("foreach") funktioniert für Arrays und Dinge, die das implementieren Iterable
Schnittstelle .
Es ist auch analoger Iterator
als zu Iterable
, daher wäre es nicht sinnvoll Enumeration
, mit foreach zu arbeiten, wenn es Iterator
nicht auch so wäre (und es tut es nicht).
Enumeration
wird auch zugunsten von entmutigt Iterator
.
Enumeration
wird nicht implementiert Iterable
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))) {
...
}
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.
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