Necesito averiguar la cantidad de elementos 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 ya no necesito los objetos en el Iterable:
it = values.iterator();
while (it.hasNext()) {
it.remove();
sum++;
}
Un punto de referencia a pequeña escala no mostró mucha diferencia de rendimiento, ¿algún comentario u otra idea para este problema?
remove()
sin llamar denext()
antemano.Respuestas:
TL; DR: Utilice el método
Iterables.size(Iterable)
de utilidad 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
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, de hecho an
ArrayList
, eliminar 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 en
values
realidad sea unCollection
y no solo unIterable
, verifique esto y llamesize()
en caso de que:if (values instanceof Collection<?>) { return ((Collection<?>)values).size(); } // use Iterator here...
La llamada a la
size()
voluntad general será mucho más rápido que contar el número de elementos, y este truco es exactamente lo queIterables.size(Iterable)
de guayaba hace por usted.fuente
values
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 divisores para colecciones lo harán, pero es posible que tenga problemas si proviene de un archivo
HashSet
o,ResultSet
por ejemplo.Puedes consultar el javadoc aquí.
Si Java 8 no es una opción , o si no sabe de dónde viene 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; }
fuente
Quizás sea un poco tarde, pero puede ayudar a alguien. Me encontré con un problema similar
Iterable
en mi base de código y la solución fue usarfor each
sin llamar explícitamentevalues.iterator();
.int size = 0; for(T value : values) { size++; }
fuente
Puede convertir su iterable a una lista y luego usar .size () en él.
En aras de la claridad, el método anterior requerirá la siguiente importación:
import com.google.common.collect.Lists;
fuente
Estrictamente hablando, Iterable no tiene tamaño. Piense en la estructura de datos como un ciclo.
Y piense en la siguiente instancia 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(); }}; }};
fuente
Yo optaría por
it.next()
la sencilla razón de quenext()
se garantiza que se implementará, mientras queremove()
es una operación opcional.fuente
remove
ya se han señalado como la forma incorrecta de contar elementos de unIterator
, por lo que realmente no importa si lo que no vamos a hacer se implementa o no.remove
se implementa, ¿por qué sería incorrecto usarlo? Por cierto, los votos negativos se usan típicamente para respuestas incorrectas o respuestas que dan malos consejos. No veo cómo esta respuesta califica para nada de eso.java 8 y superior
StreamSupport.stream(data.spliterator(), false).count();
fuente
En cuanto a mí, estos son solo métodos diferentes. El primero deja el objeto en el que está iterando sin cambios, mientras que el segundo lo deja vacío. La pregunta es qué quieres hacer. La complejidad de la eliminación se basa en la implementación de su objeto iterable. Si está utilizando Colecciones, solo obtenga el tamaño propuesto por Kazekage Gaara, generalmente es el mejor enfoque en cuanto al rendimiento.
fuente
¿Por qué no usas simplemente el
size()
método en tuCollection
para obtener la cantidad de elementos?Iterator
está destinado a iterar, nada más.fuente
Iterator
yIterable
. Vea la respuesta votada de la manera correcta.En lugar de usar bucles y contar cada elemento o usar una biblioteca de terceros, simplemente podemos encasillar el iterable en ArrayList y obtener su tamaño.
fuente