Respuestas:
Mejor use una biblioteca como Guava :
import com.google.common.collect.Lists;
Iterator<Element> myIterator = ... //some iterator
List<Element> myList = Lists.newArrayList(myIterator);
Otro ejemplo de guayaba:
ImmutableList.copyOf(myIterator);
o Colecciones de Apache Commons :
import org.apache.commons.collections.IteratorUtils;
Iterator<Element> myIterator = ...//some iterator
List<Element> myList = IteratorUtils.toList(myIterator);
En Java 8, puede usar el nuevo forEachRemaining
método que se ha agregado a la Iterator
interfaz:
List<Element> list = new ArrayList<>();
iterator.forEachRemaining(list::add);
::
? que nombre tiene parece una referencia directa a list.add (); y parece también algo nuevo de java8; ¡y gracias! :)
::
sintaxis es nueva en Java 8, y se refiere a una "referencia de método", que es una forma abreviada de lambda. Consulte aquí para obtener más información: docs.oracle.com/javase/tutorial/java/javaOO/…
iterator
viene es un símbolo no resuelto
iterator
.
Puede copiar un iterador a una nueva lista como esta:
Iterator<String> iter = list.iterator();
List<String> copy = new ArrayList<String>();
while (iter.hasNext())
copy.add(iter.next());
Eso supone que la lista contiene cadenas. Realmente no hay una manera más rápida de recrear una lista desde un iterador, estás atrapado en recorrerla a mano y copiar cada elemento en una nueva lista del tipo apropiado.
EDITAR:
Aquí hay un método genérico para copiar un iterador a una nueva lista de forma segura:
public static <T> List<T> copyIterator(Iterator<T> iter) {
List<T> copy = new ArrayList<T>();
while (iter.hasNext())
copy.add(iter.next());
return copy;
}
Úselo así:
List<String> list = Arrays.asList("1", "2", "3");
Iterator<String> iter = list.iterator();
List<String> copy = copyIterator(iter);
System.out.println(copy);
> [1, 2, 3]
Tenga en cuenta que hay una diferencia entre Iterable
y Iterator
.
Si tiene un Iterable
, entonces con Java 8 puede usar esta solución:
Iterable<Element> iterable = createIterable();
List<Element> array = StreamSupport
.stream(iterable.spliterator(), false)
.collect(Collectors.toList());
Como sé Collectors.toList()
crea ArrayList
instancia.
En realidad, en mi opinión, también se ve bien en una línea.
Por ejemplo, si necesita regresar List<Element>
de algún método:
return StreamSupport.stream(iter.spliterator(), false).collect(Collectors.toList());
Iterable
iterator
. Son completamente diferentes.
Iterator
copia de seguridad a un solo uso Iterable
mediante el uso () -> iterator
. Esto puede ser útil en situaciones como esta, pero permítanme enfatizar lo importante nuevamente: puede usar este método solo si un solo uso Iterable
es aceptable. Llamar iterable.iterator()
más de una vez dará resultados inesperados. La respuesta anterior se convierte entonces enIterator<Element> iterator = createIterator();
List<Element> array = StreamSupport.stream(((Iterable<Element>) () -> iterable).spliterator(), false).collect(toList());
También puede usarlo IteratorUtils
desde Apache commons-collections , aunque no admite genéricos:
List list = IteratorUtils.toList(iterator);
Solución bastante concisa con Java 8 simple usando java.util.stream
:
public static <T> ArrayList<T> toArrayList(final Iterator<T> iterator) {
return StreamSupport
.stream(
Spliterators
.spliteratorUnknownSize(iterator, Spliterator.ORDERED), false)
.collect(
Collectors.toCollection(ArrayList::new)
);
}
iterator.forEachRemaining( list::add )
, también nuevo en Java 8, es mucho más conciso. Insertar la variable de lista en Collector
no mejora la lectura en este caso, ya que debe ser compatible con a Stream
y a Spliterator
.
List result = new ArrayList();
while (i.hasNext()){
result.add(i.next());
}
Probar StickyList
de Cactoos :
List<String> list = new StickyList<>(iterable);
Descargo de responsabilidad: soy uno de los desarrolladores.
Iterable
! =Iterator
Solo quiero señalar una solución aparentemente obvia que NO funcionará:
Lista lista = Stream.generate (iterador :: siguiente) .collect (Collectors.toList ());
Esto se debe a Stream#generate(Supplier<T>)
que solo puede crear secuencias infinitas, no espera que su argumento arroje NoSuchElementException
(eso es lo Iterator#next()
que hará al final).
La respuesta de xehpuk debe usarse en su lugar si Iterator → Stream → List es su elección.
usa google guava !
Iterable<String> fieldsIterable = ...
List<String> fields = Lists.newArrayList(fieldsIterable);
++
Aquí, en este caso, si quieres la forma más rápida posible, entonces for loop
es mejor.
El iterador sobre un tamaño de muestra de 10,000 runs
tomas 40 ms
donde en cuanto a tomas de bucle2 ms
ArrayList<String> alist = new ArrayList<String>();
long start, end;
for (int i = 0; i < 1000000; i++) {
alist.add(String.valueOf(i));
}
ListIterator<String> it = alist.listIterator();
start = System.currentTimeMillis();
while (it.hasNext()) {
String s = it.next();
}
end = System.currentTimeMillis();
System.out.println("Iterator start: " + start + ", end: " + end + ", delta: "
+ (end - start));
start = System.currentTimeMillis();
int ixx = 0;
for (int i = 0; i < 100000; i++) {
String s = alist.get(i);
}
System.out.println(ixx);
end = System.currentTimeMillis();
System.out.println("for loop start: " + start + ", end: " + end + ", delta: "
+ (end - start));
Eso supone que la lista contiene cadenas.
for
bucle y acceder a los elementos de una lista get(i)
es más rápido que usar un iterador ... pero eso no es lo que pedía el OP, mencionó específicamente que se proporciona un iterador como entrada.
get(int)
bucle, solo está viendo 100k de las entradas de 1m. Si cambia ese ciclo para que sea it.size()
, verá que estos 2 métodos están cerca de la misma velocidad. En general, este tipo de pruebas de velocidad de Java proporcionan información limitada sobre el rendimiento en la vida real y deben considerarse con escepticismo.