Un iterador no corresponde necesariamente a algo con un "recuento" ...
Oliver Charlesworth
Los iteradores son lo que son; para iterar al siguiente objeto de una colección (puede ser cualquier cosa como conjunto, matriz, etc.) ¿Por qué necesitan decir el tamaño cuando no les importa para qué están tratando de iterar? to provide an implementation-independent method for access, in which the user does not need to know whether the underlying implementation is some form of array or of linked list, and allows the user go through the collection without explicit indexing.penguin.ewu.edu/~trolfe/LinkedSort/Iterator.html
ecle
Respuestas:
67
Si acaba de obtener el iterador, entonces eso es lo que tendrá que hacer: no sabe cuántos elementos le quedan para iterar, por lo que no puede consultarlo para obtener ese resultado. Hay métodos de utilidad que parecerán hacer esto (como Iterators.size()en Guava), pero en el fondo solo realizan aproximadamente la misma operación.
Sin embargo, muchos iteradores provienen de colecciones, que a menudo puede consultar por su tamaño. Y si se trata de una clase creada por el usuario para la que está obteniendo el iterador, puede buscar proporcionar un método size () en esa clase.
En resumen, en la situación en la que solo tiene el iterador, entonces no hay mejor manera, pero la mayoría de las veces tiene acceso a la colección u objeto subyacente desde el cual puede obtener el tamaño directamente.
Tenga cuidado con el efecto secundario de Iterators.size(...)(mencionado en otros comentarios a continuación y en java-doc): "Devuelve el número de elementos que quedan en el iterador. El iterador quedará agotado: su método hasNext () devolverá falso". Eso significa que ya no puede usar el Iterador después. Lists.newArrayList(some_iterator);puede ayudar.
List list =Lists.newArrayList(some_iterator);int count = list.size();
Úselo si también necesita acceder a los elementos del iterador después de obtener su tamaño. Al usarlo Iterators.size(), ya no puede acceder a los elementos iterados.
@LoveToCode Menos eficiente que el ejemplo de la pregunta original
Invierno
2
Claro, crear un nuevo objeto con todos los elementos es más lento que simplemente iterar y descartar. En mi humilde opinión, esta solución es una línea que mejora la legibilidad del código. Lo uso mucho para colecciones con pocos elementos (hasta 1000) o cuando la velocidad no es un problema.
Tashuhka
7
Si todo lo que tiene es el iterador, entonces no, no hay una forma "mejor". Si el iterador proviene de una colección, podría usarlo por tamaño.
Tenga en cuenta que Iterator es solo una interfaz para atravesar valores distintos, muy bien tendría un código como este
newIterator<Long>(){finalRandom r =newRandom();@Overridepublicboolean hasNext(){returntrue;}@OverridepublicLong next(){return r.nextLong();}@Overridepublicvoid remove(){thrownewIllegalArgumentException("Not implemented");}};
o
newIterator<BigInteger>(){BigInteger next =BigInteger.ZERO;@Overridepublicboolean hasNext(){returntrue;}@OverridepublicBigInteger next(){BigInteger current = next;
next = next.add(BigInteger.ONE);return current;}@Overridepublicvoid remove(){thrownewIllegalArgumentException("Not implemented");}};
No hay forma más eficiente, si todo lo que tiene es el iterador. Y si el iterador solo se puede usar una vez, entonces obtener el recuento antes de obtener el contenido del iterador es ... problemático.
La solución es cambiar su aplicación para que no necesite el recuento o obtener el recuento por algún otro medio. (Por ejemplo, pase a en Collectionlugar de Iterator...)
El objeto iterador contiene el mismo número de elementos que su colección.
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.
to provide an implementation-independent method for access, in which the user does not need to know whether the underlying implementation is some form of array or of linked list, and allows the user go through the collection without explicit indexing.
penguin.ewu.edu/~trolfe/LinkedSort/Iterator.htmlRespuestas:
Si acaba de obtener el iterador, entonces eso es lo que tendrá que hacer: no sabe cuántos elementos le quedan para iterar, por lo que no puede consultarlo para obtener ese resultado. Hay métodos de utilidad que parecerán hacer esto (como
Iterators.size()
en Guava), pero en el fondo solo realizan aproximadamente la misma operación.Sin embargo, muchos iteradores provienen de colecciones, que a menudo puede consultar por su tamaño. Y si se trata de una clase creada por el usuario para la que está obteniendo el iterador, puede buscar proporcionar un método size () en esa clase.
En resumen, en la situación en la que solo tiene el iterador, entonces no hay mejor manera, pero la mayoría de las veces tiene acceso a la colección u objeto subyacente desde el cual puede obtener el tamaño directamente.
fuente
Iterators.size(...)
(mencionado en otros comentarios a continuación y en java-doc): "Devuelve el número de elementos que quedan en el iterador. El iterador quedará agotado: su método hasNext () devolverá falso". Eso significa que ya no puede usar el Iterador después.Lists.newArrayList(some_iterator);
puede ayudar.Usando la biblioteca de Guava :
Internamente, solo itera sobre todos los elementos, por lo que es solo por conveniencia.
fuente
Su código le dará una excepción cuando llegue al final del iterador. Podrías hacerlo:
Si tuviera acceso a la colección subyacente, podría llamar
coll.size()
...EDITAR OK ha modificado ...
fuente
Siempre tendrás que iterar. Sin embargo, puede usar Java 8, 9 para hacer el conteo sin hacer un bucle explícito:
Aquí hay una prueba:
Esto imprime:
Es bastante interesante que puede paralelizar la operación de conteo aquí cambiando la
parallel
bandera en esta llamada:fuente
Usando la biblioteca de Guava , otra opción es convertir el archivo
Iterable
aList
.Úselo si también necesita acceder a los elementos del iterador después de obtener su tamaño. Al usarlo
Iterators.size()
, ya no puede acceder a los elementos iterados.fuente
Si todo lo que tiene es el iterador, entonces no, no hay una forma "mejor". Si el iterador proviene de una colección, podría usarlo por tamaño.
Tenga en cuenta que Iterator es solo una interfaz para atravesar valores distintos, muy bien tendría un código como este
o
fuente
No hay forma más eficiente, si todo lo que tiene es el iterador. Y si el iterador solo se puede usar una vez, entonces obtener el recuento antes de obtener el contenido del iterador es ... problemático.
La solución es cambiar su aplicación para que no necesite el recuento o obtener el recuento por algún otro medio. (Por ejemplo, pase a en
Collection
lugar deIterator
...)fuente
para Java 8 puedes usar
fuente
El objeto iterador contiene el mismo número de elementos que su colección.
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.
fuente
a
, pero soloi
?