java - Enumeración genérica a convertidor iterable
collections open-source (5)
HttpServletRequest está utilizando una gran cantidad de java.util.Enumeration. Me gustaría usarlos para cada uno, así que necesito convertirlos en interables. Esto no es un problema, pero como tengo más de un proyecto que lo necesita, necesito una biblioteca para hacerlo. Preferiría no hacer la mía. ¿Existe alguna biblioteca estándar que admita este tipo de decoración?
¿Hay una construcción incorporada para convertir una enumeración en un iterable?
Aquí está el javadoc de la guayaba con respecto a la conversión de una enumeración a iterador (no iterable):
Public static UnmodifiableIterator forEnumeration (enumeración de enumeración)
Adapta una enumeración a la interfaz del iterador.
Este método no tiene equivalente en Iterables porque es imposible ver una enumeración como un Iterable. Sin embargo, el contenido se puede copiar en una colección utilizando Collections.list (java.util.Enumeration).
Además, la implementación actual de las colecciones comunes de apache no es compatible con las características y API de Java 5 como Iterable, por lo que no hay ninguna posibilidad.
Sin embargo, hay algunos métodos en esas bibliotecas que le permiten cambiar una enumeración a una colección que es iterable y usarla (aunque copian implícitamente sus datos).
Por ejemplo, transforme a una lista con EnumerationUtils.toList(enumeration) .
Edición: debido a algunas preguntas en la pregunta, intentaré resumir por qué los fabricantes de guayaba (y yo) no sentimos que una enumeración se pueda convertir en una iterable.
Un iterable crea instancias de iterador, alguien que lee el código (o API) puede asumir que cada llamada a iterator () produce una nueva instancia de iterador que comienza la enumeración desde el primer elemento. Si hacemos una conversión simple entre un iterador (o enumeración) y un iterable, entonces el usuario de la API debe saber que una llamada a iterador () cambia el estado del objeto y que 2 llamadas consecutivas pueden comportarse de manera extraña. Aquí hay un ejemplo:
Iterable<String> iter = magicFunction(enumeration);
for (String s : iter) {
if ("hello".equals(s))
break;
}
for (String s : iter) {
if ("world".equals(s))
return true;
}
return false;
Si se implementa como una conversión simple (O (1)) El método anterior se comporta de manera diferente para diferentes entradas: ["hello","world"]
devolvería true
, mientras que ["world","hello"]
devolvería false
. Esto no es evidente de inmediato al mirar el código y puede ser la causa de muchos errores frustrantes. Por lo tanto, creo que tiene sentido no tener este método de utilidad.
Eche un vistazo a este artículo: http://www.java2s.com/Code/Java/Collections-Data-Structure/TreatanEnumerationasanIterable.htm
Parece exactamente lo que necesitas.
ACTUALIZADO Se agregó el código para futuras referencias en caso de que el enlace se rompa.
final Request request2 = request;
Iterable<String> headerNamesIterable = new Iterable<String>(){
public Iterator<T> iterator(){
return Iterators.forEnumeration(request2.getHeaderNames())
}
}
Iterable<String> headersIterableName1 = new Iterable<String>(){
public Iterator<T> iterator(){
return Iterators.forEnumeration(request2.getHeaders("name1"))
}
}
En mi opinión, la forma documentada es la más sencilla, por lo que no es necesario convertirla en Iterator:
https://docs.oracle.com/javase/1.5.0/docs/api/java/util/Enumeration.html
for (Enumeration<E> e = v.elements(); e.hasMoreElements();)
System.out.println(e.nextElement());
Tienes dos soluciones:
Lo primero es consumir el enumerador en una colección que sea iterable (como lo describe @skaffman). Esto agregará O (n) como lo señaló @Michael
En los casos en que tenga acceso al método que creó el enumerador, puede incluirlo en un Iterable sin pagar el costo. En tu caso puedes crear un Iterable con:
import java.util.Enumeration;
import java.util.Iterator;
/**
* @since 4.37
* @author Jaroslav Tulach
*/
public class Utils {
public static <E> Iterable<E> iterable(final Enumeration<E> enumeration) {
if (enumeration == null) {
throw new NullPointerException();
}
return new Iterable<E>() {
public Iterator<E> iterator() {
return new Iterator<E>() {
public boolean hasNext() {
return enumeration.hasMoreElements();
}
public E next() {
return enumeration.nextElement();
}
public void remove() {
throw new UnsupportedOperationException();
}
};
}
};
}
}
En este caso, puede iterar varias veces en los iteradores creados por los objetos iterables.
java.util.Collections
tiene un método de list
que copia una Enumeration
en una List
, que luego puede utilizar en un bucle para cada (ver javadoc ).