java - ejemplo - list iterator c++
Convertir Iterador a ArrayList (12)
Dado el Iterator<Element>
, ¿cómo podemos convertir ese Iterator
en ArrayList<Element>
(o List<Element>
) de la mejor manera y de la manera más rápida posible, de modo que podamos usar las operaciones de ArrayList
en él como get(index)
, add(element)
, etc.
Aquí, en este caso, si desea la forma más rápida posible, entonces for loop
es mejor.
El iterador sobre un tamaño de muestra de 10,000 runs
toma 40 ms
mientras que el bucle toma 2 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 suponiendo que la lista contiene cadenas.
El método Java 8 forEachRemaining en Iterator se puede utilizar aquí:
List<Element> elementList = new ArrayList<>();
iterator.forEachRemaining(elementList::add);
En Java 8, puede usar el nuevo método forEachRemaining
que se agregó a la interfaz del Iterator
:
List<Element> list = new ArrayList<>();
iterator.forEachRemaining(list::add);
Mejor usar una biblioteca como la 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 Apache Commons Colecciones :
import org.apache.commons.collections.IteratorUtils;
Iterator<Element> myIterator = ...//some iterator
List<Element> myList = IteratorUtils.toList(myIterator);
Note que hay una diferencia entre Iterable
e Iterator
.
Si tienes un Iterable
, entonces con Java 8 puedes usar esta solución:
Iterable<Element> iterable = createIterable();
List<Element> array = StreamSupport
.stream(iterable.spliterator(), false)
.collect(Collectors.toList());
Como sé, Collectors.toList()
crea una instancia de ArrayList
.
En realidad, en mi opinión, también se ve bien en una línea.
Por ejemplo, si necesita devolver la List<Element>
desde algún método:
return StreamSupport.stream(iter.spliterator(), false).collect(Collectors.toList());
Prueba StickyList
de Cactoos :
List<String> list = new StickyList<>(iterator);
Descargo de responsabilidad: soy uno de los desarrolladores.
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 suponiendo que la lista contiene cadenas. Realmente no hay una forma más rápida de recrear una lista de un iterador, te quedas atascado atravesándola a mano y copiando 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 una manera segura para el tipo:
public static <T> List<T> copyIterator(Iterator<T> iter) {
List<T> copy = new ArrayList<T>();
while (iter.hasNext())
copy.add(iter.next());
return copy;
}
Úsalo 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]
Solo quiero señalar una solución aparentemente obvia que NO funcionará:
List list = Stream.generate(iterator::next)
.collect(Collectors.toList());
Esto se debe a que Stream#generate(Supplier<T>)
puede crear solo flujos infinitos, no espera que su argumento arroje NoSuchElementException
(eso es lo que Iterator#next()
hará al final).
share debe usar en su lugar si Iterator → Stream → List way es su elección.
Solución bastante concisa con Java 8 simple utilizando 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)
);
}
También puede usar IteratorUtils
de commons-collections Apache, aunque no es compatible con los genéricos:
List list = IteratorUtils.toList(iterator);
utiliza google guava !
Iterable<String> fieldsIterable = ...
List<String> fields = Lists.newArrayList(fieldsIterable);
++
List result = new ArrayList();
while (i.hasNext()){
result.add(i.next());
}