获取Java中Iterable的大小

js8*_*s84 75 java iterable

我需要弄清楚IterableJava中的元素数量.我知道我可以这样做:

Iterable values = ...
it = values.iterator();
while (it.hasNext()) {
  it.next();
  sum++;
}
Run Code Online (Sandbox Code Playgroud)

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

it = values.iterator();
while (it.hasNext()) {
  it.remove();
  sum++;
}
Run Code Online (Sandbox Code Playgroud)

一个小规模的基准测试没有表现出太大的性能差异,这个问题的任何评论或其他想法?

Phi*_*ler 109

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

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

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

一般情况下,如果有机会values实际上是a Collection而不仅仅是a Iterable,请检查并调用size()以防万一:

if (values instanceof Collection<?>) {
  return ((Collection<?>)values).size();
}
// use Iterator here...
Run Code Online (Sandbox Code Playgroud)

要将呼叫size()通常会比计算元素的数量快得多,这一招是什么Iterables.size(Iterable)番石榴为你做.

  • 如果您使用Java 8,请在其中创建Stream和count元素:Stream.of(myIterable).count() (8认同)

Arn*_*udR 36

如果您正在使用Java 8,您可以使用:

Iterable values = ...
long size = values.spliterator().getExactSizeIfKnown();
Run Code Online (Sandbox Code Playgroud)

它只有在可迭代源具有确定的大小时才有效.大多数收集的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;
    }
Run Code Online (Sandbox Code Playgroud)

  • 来人,给这家伙一枚奖章。 (2认同)

pil*_*lot 16

这可能有点晚了,但可能对某人有所帮助.我Iterable在我的代码库中遇到了类似的问题,解决方案是在for each没有显式调用的情况下使用values.iterator();.

int size = 0;
for(T value : values) {
   size++;
}
Run Code Online (Sandbox Code Playgroud)

  • 对我来说,这是一种直观的方法,我很欣赏。几分钟前刚用过。谢谢。 (2认同)
  • 是的,它是直观的,但遗憾的是你必须压制一个未使用的警告值... (2认同)

卢声远*_* Lu 6

严格来说,Iterable没有大小.认为数据结构就像一个循环.

并考虑遵循Iterable实例,没有大小:

    new Iterable(){

        @Override public Iterator iterator() {
            return new Iterator(){

                @Override
                public boolean hasNext() {
                    return isExternalSystemAvailble();
                }

                @Override
                public Object next() {
                    return fetchDataFromExternalSystem();
                }};
        }};
Run Code Online (Sandbox Code Playgroud)


sna*_*cks 6

您可以将您的iterable转换为列表,然后使用.size().

Lists.newArrayList(iterable).size();
Run Code Online (Sandbox Code Playgroud)

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

import com.google.common.collect.Lists;
Run Code Online (Sandbox Code Playgroud)

  • Lists 是一个 Guava 类 (3认同)