method implementar hasnext example collection java iterable

implementar - Obtener el tamaño de un Iterable en Java



iterator java package (9)

Necesito averiguar la cantidad de elementos en un Iterable en Java. Sé que puedo hacerlo:

Iterable values = ... it = values.iterator(); while (it.hasNext()) { it.next(); sum++; }

También podría hacer algo como esto, porque no necesito más objetos en Iterable:

it = values.iterator(); while (it.hasNext()) { it.remove(); sum++; }

¿Un punto de referencia a pequeña escala no mostró mucha diferencia de rendimiento, ningún comentario u otra idea para este problema?


¿Por qué no simplemente usas el método size() en tu Collection para obtener la cantidad de elementos?

Iterator solo debe iterar, nada más.


En cuanto a mí, estos son solo métodos diferentes. El primero deja inalterado el objeto que estás iterando, mientras que los segundos lo dejan vacío. La pregunta es qué quieres hacer. La complejidad de eliminar se basa en la implementación de su objeto iterable. Si está utilizando Colecciones, simplemente obtenga el tamaño como fue propuesto por Kazekage Gaara, generalmente es el mejor enfoque en cuanto al rendimiento.


En lugar de usar bucles y contar cada elemento o usar una biblioteca de terceros, podemos simplemente encasillar el iterable en ArrayList y obtener su tamaño.

((ArrayList) iterable).size();


Esto es quizás un poco tarde, pero puede ayudar a alguien. Me encontré con un problema similar con Iterable en mi base de código y la solución fue utilizar for each sin llamar explícitamente a values.iterator(); .

int size = 0; for(T value : values) { size++; }


Estrictamente hablando, Iterable no tiene tamaño. Piensa en la estructura de datos como un ciclo.

Y piense en seguir una instancia de Iterable, sin tamaño:

new Iterable(){ @Override public Iterator iterator() { return new Iterator(){ @Override public boolean hasNext() { return isExternalSystemAvailble(); } @Override public Object next() { return fetchDataFromExternalSystem(); }}; }};


Puede convertir su iterable en una lista y luego usar .size () en ella.

Lists.newArrayList(iterable).size();

En aras de la claridad, el método anterior requerirá la siguiente importación:

import com.google.common.collect.Lists;


Si está trabajando con Java 8, puede usar:

Iterable values = ... long size = values.spliterator().getExactSizeIfKnown();

solo funcionará si la fuente iterable tiene un tamaño determinado. La mayoría de los Spliterators for Collections lo harán, pero puede tener problemas si proviene de un HashSet o un ResultSet por ejemplo.

Puedes consultar el javadoc aquí.

Si Java 8 no es una opción , o si no sabe de dónde proviene el iterable, puede usar el mismo enfoque que guava:

if (iterable instanceof Collection) { return ((Collection<?>) iterable).size(); } else { int count = 0; Iterator iterator = iterable.iterator(); while(iterator.hasNext()) { iterator.next(); count++; } return count; }


Yo iría por it.next() por la sencilla razón de que se garantiza que next() se implementará, mientras que remove() es una operación opcional.

E next()

Devuelve el siguiente elemento en la iteración.

void remove()

Elimina de la colección subyacente el último elemento devuelto por el iterador (operación opcional) .


TL; DR: utilice el método de utilidad Iterables.size(Iterable) de la gran biblioteca de Guava .

De sus dos fragmentos de código, debe usar el primero, porque el segundo eliminará todos los elementos de los values , por lo que estará vacío después. Cambiar una estructura de datos para una consulta simple como su tamaño es muy inesperado.

Para el rendimiento, esto depende de su estructura de datos. Si es, por ejemplo, una ArrayList , quitar los elementos desde el principio (lo que está haciendo su segundo método) es muy lento (calcular el tamaño se convierte en O (n * n) en lugar de O (n) como debería ser).

En general, si existe la posibilidad de que los values sean en realidad una Collection y no solo un Iterable , verifique esto y llame al size() en caso de que:

if (values instanceof Collection<?>) { return ((Collection<?>)values).size(); } // use Iterator here...

La llamada al size() generalmente será mucho más rápido que contar la cantidad de elementos, y este truco es exactamente lo que Iterables.size(Iterable) de Guava hace por ti.