在Java中获取Iterable的大小

我需要弄清楚Java中的Iterable元素的数量。 我知道我可以做到这一点:

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

我也可以这样做,因为我不需要进一步的Iterable中的对象:

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

一个小规模的基准并没有performance出太多的性能差异,对这个问题的任何意见或其他想法?

TL; DR:使用伟大的番石榴库的实用方法Iterables.size(Iterable)

在你的两个代码片段中,你应该使用第一个代码片段,因为第二个代码片段将从values移除所有元素,所以之后它是空的。 更改一个简单的查询,如其大小的数据结构是非常意外的。

为了性能,这取决于你的数据结构。 如果它实际上是一个ArrayList ,那么从头开始删除元素(你的第二个方法在做什么)是非常慢的(计算大小变成O(n * n)而不是O(n),因为它应该是这样)。

一般情况下,如果有可能values实际上是一个Collection ,而不仅是一个Iterable ,请检查这个和调用size()以防万一:

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

size()的调用通常比计算元素的数量快得多,这个技巧正是Guava的 Iterables.size(Iterable)为你所做的。

如果你正在使用java 8,你可以使用:

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

它只会在迭代源具有确定的大小时才起作用。 Collections的大部分Spliterator都可以,但是如果它来自HashSetResultSet ,则可能会遇到问题。

你可以在这里检查javadoc。

如果Java 8不是一个选项 ,或者如果您不知道迭代来自哪里,那么可以使用与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; } 

这可能有点晚,但可能有助于某人。 我遇到类似的问题与我的代码库中的Iterable和解决scheme是使用for each没有显式调用values.iterator();

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

严格来说,Iterable没有规模。 认为数据结构像一个循环。

并考虑下面的Iterable实例,没有大小:

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

你可以把你的iterable转换成一个列表,然后在其上使用.size()。

 Lists.newArrayList(iterable).size(); 

为了清楚起见,上述方法将需要以下导入:

 import com.google.common.collect.Lists; 

我会去it.next()的原因是, next()是保证实现,而remove()是一个可选的操作。

 E next() 

返回迭代中的下一个元素。

 void remove() 

从底层集合中删除迭代器返回的最后一个元素(可选操作)

至于我,这些只是不同的方法。 第一个离开你迭代的对象保持不变,而秒保持空白。 问题是你想做什么。 删除的复杂性基于您的可迭代对象的实现。 如果你正在使用集合 – 只是像Kazekage Gaara所提出的那样获得大小 – 它通常是performance最好的方法。

你为什么不简单地使用你的Collectionsize()方法来获取元素的数量?

Iterator只是为了迭代,没有别的。