recorrer patron objetos lista linkedlist hasnext ejemplo java iterator

java - patron - ¿Cuál es la mejor forma de obtener el recuento/longitud/tamaño de un iterador?



recorrer arraylist java foreach (8)

¿Existe una forma "computacionalmente" rápida de obtener el conteo de un iterador?

int i = 0; for ( ; some_iterator.hasNext() ; ++i ) some_iterator.next();

... parece una pérdida de ciclos de CPU.


El objeto iterador contiene la misma cantidad de elementos que su colección contenía.

List<E> a =...; Iterator<E> i = a.iterator(); int size = a.size();//Because iterators size is equal to list a''s size.

Pero en lugar de obtener el tamaño del iterador e iterar a través del índice 0 hasta ese tamaño, es mejor iterar a través del método next () del iterador.


No hay una manera más eficiente, si todo lo que tienes es el iterador. Y si el iterador solo puede usarse una vez, obtener el conteo antes de obtener los contenidos del iterador es ... problemático.

La solución es cambiar su aplicación para que no necesite el conteo u obtener el conteo por otros medios. (Por ejemplo, pasar una Collection lugar de Iterator ...)


Otra opción es convertir Iterable en una List .

int count = Lists.newArrayList(some_iterator).size();


Si acaba de obtener el iterador, entonces eso es lo que tendrá que hacer, no sabe cuántos elementos tiene que iterar, por lo que no puede consultarlo para ese resultado.

Sin embargo, muchos iteradores provienen de colecciones, que a menudo puede consultar para su tamaño. Y si es una clase hecha por el usuario para la que está obteniendo el iterador, podría intentar proporcionar un método de tamaño () en esa clase.

En resumen, en la situación en la que solo tiene el iterador, no hay una mejor manera, pero con mucha frecuencia tiene acceso a la colección u objeto subyacente desde el que puede obtener el tamaño directamente.


Si todo lo que tienes es el iterador, entonces no, no hay una "mejor" manera. Si el iterador proviene de una colección, puede hacerlo para el tamaño.

Tenga en cuenta que Iterator es solo una interfaz para atravesar distintos valores, muy bien tendría un código como este

new Iterator<Long>() { final Random r = new Random(); @Override public boolean hasNext() { return true; } @Override public Long next() { return r.nextLong(); } @Override public void remove() { throw new IllegalArgumentException("Not implemented"); } };

o

new Iterator<BigInteger>() { BigInteger next = BigInteger.ZERO; @Override public boolean hasNext() { return true; } @Override public BigInteger next() { BigInteger current = next; next = next.add(BigInteger.ONE); return current; } @Override public void remove() { throw new IllegalArgumentException("Not implemented"); } };


Siempre tendrás que iterar. Sin embargo, puede usar Java 8, 9 para hacer el conteo sin bucle explícitamente:

Iterable<Integer> newIterable = () -> iter; long count = StreamSupport.stream(newIterable.spliterator(), false).count();

Aquí hay una prueba:

public static void main(String[] args) throws IOException { Iterator<Integer> iter = Arrays.asList(1, 2, 3, 4, 5).iterator(); Iterable<Integer> newIterable = () -> iter; long count = StreamSupport.stream(newIterable.spliterator(), false).count(); System.out.println(count); }

Esto imprime:

5

Es lo suficientemente interesante como para paralelizar la operación de recuento aquí cambiando la bandera parallel en esta llamada:

long count = StreamSupport.stream(newIterable.spliterator(), *true*).count();


Su código le dará una excepción cuando llegue al final del iterador. Podrías hacerlo:

int i = 0; while(iterator.hasNext()) { i++; iterator.next(); }

Si tuviera acceso a la colección subyacente, podría llamar a coll.size() ...

EDITAR OK has modificado ...


Usando la biblioteca de Guava :

int size = Iterators.size(iterator);

Internamente solo itera sobre todos los elementos, por lo que es solo por conveniencia.