在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都可以,但是如果它来自HashSet
或ResultSet
,则可能会遇到问题。
你可以在这里检查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最好的方法。
你为什么不简单地使用你的Collection
的size()
方法来获取元素的数量?
Iterator
只是为了迭代,没有别的。