Por qué no puedo hacer:¿Por qué no puedo usar foreach en Java Enumeration?
Enumeration e = ...
for (Object o : e)
...
Por qué no puedo hacer:¿Por qué no puedo usar foreach en Java Enumeration?
Enumeration e = ...
for (Object o : e)
...
Debido Enumeration<T>
no se extiende Iterable<T>
. Aquí hay un example of making Iterable Enumerations.
cuanto a por qué eso es una pregunta interesante. Esta no es exactamente su pregunta, pero arroja algo de luz sobre ella. Desde el Java Collections API Design FAQ:
¿Por qué no se extienden iterador enumeración?
Vemos los nombres de métodos para Enumeración como desafortunado. Son muy largos, y se usan con mucha frecuencia. dado que estábamos añadiendo un método y crear un marco completamente nuevo, que sentimos que sería absurdo no aprovechar la oportunidad de mejorar las nombres. Por supuesto, podríamos apoyar a los nuevos y viejos nombres en iterador, pero no parece que vale la pena .
Eso básicamente me sugiere que Sun quiere distanciarse de la enumeración, que es muy temprano Java con una sintaxis bastante detallado.
Siguiente pregunta: ¿por qué las enumeraciones no se pueden modificar? http://stackoverflow.com/questions/27240/why-arent-enumerations-iterable –
¿Hay una diferencia semántica entre los dos? (No estoy familiarizado con la clase Iterable)? ¿Por qué no tener también trabajo en Enumeration? – ripper234
Porque las enumeraciones son más parecidas a Iterator, no Iterable (vea la pregunta de stackoverflow publicada por mmyers). Como solución alternativa, puede hacer 'for (; e.hasMoreElements();) {e.getNextElement(); } ' – Tim
El new-style-for-loop ("foreach") funciona en arreglos y cosas que implementan la interfaz Iterable
.
También es más análogo a Iterator
que a Iterable
, por lo que no tendría sentido que Enumeration
trabajar con foreach menos Iterator
también lo hizo (y no lo hace). Enumeration
también se desanima a favor de Iterator
.
Tengamos cuidado con los términos aquí. La depreciación significa algo muy específico al discutir las API. Se desaconseja el uso de la enumeración, pero no está en desuso. – ykaganovich
ykaganovich: buen punto. He corregido el texto en la respuesta. –
Debido a una Enumeration (y la mayoría de las clases derivadas de esta interfaz) no implementa Iterable.
Usted puede tratar de escribir su propia clase contenedora.
No debe escribir un contenedor para Enumeration que lo convierta en un Iterable más de lo que debería crear dicho contenedor para Iterator. Los objetos Iterator y Enumeration son estables con respecto a la iteración. Los Iterables no lo son. –
He resuelto este problema con dos clases muy simples, una para Enumeration
y otra para Iterator
. La envoltura enumeración es el siguiente:
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"); }
}
que puede ser utilizado ya sea con un método de utilidad estática (que es mi preferencia):
/**
* 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)) {
...
}
o por crear instancias de la clase:
for(String val: new IterableEnumeration<String>(enm)) {
...
}
Utilizando la clase de utilidad Colecciones, la enumeración puede hacerse iterable como:
Enumeration headerValues=request.getHeaders("mycustomheader");
List headerValuesList=Collections.list(headerValues);
for(Object headerValueObj:headerValuesList){
... do whatever you want to do with headerValueObj
}
Los elementos se copian en una nueva lista antes de comenzar la iteración; esta solución debe evitarse para enumeraciones largas. Las soluciones que convierten una Enumeración en un iterador tienen menos sobrecarga de memoria. –
@EmmanuelBourg pero tienen efectos secundarios, ya que las enumeraciones son estables. –
¡Esta es la respuesta más fácil! No se necesitan dependencias y es claramente legible. ¡Gracias! –
Enumeration
no implementa Iterable
y como tal no se puede utilizar directamente en un bucle foreach.Sin embargo, utilizando Apache Commons Collections es posible iterar sobre una enumeración con:
for (Object o : new IteratorIterable(new EnumerationIterator(e))) {
...
}
También es posible usar una sintaxis más corta con Collections.list()
pero esto es menos eficiente (dos iteraciones más de los elementos y más uso de memoria):
for (Object o : Collections.list(e))) {
...
}
¿se refiere a [IteratorIterable] (http://commons.apache.org/proper/commons-collections/javadocs/api-release/org/apache/commons/collections4/iterators/IteratorIterable.html)? – luckyluke
@luckyluke Sí, gracias. Arreglé el ejemplo. –
Enumeración fue reemplazado por Iterator en Java 1.2 en 1998 y se conserva para soporte heredado. La verdadera pregunta es por qué quieres usarla. ¿Posiblemente porque usas una biblioteca que te obliga a hacerlo? –
@Peter: sí, una biblioteca externa es la respuesta. – ripper234