我需要弄清楚Java中Iterable
中元素的数量。
我知道我可以这样做:
Iterable values = ...
it = values.iterator();
while (it.hasNext()) {
it.next();
sum++;
}
我也可以这样做,因为我不再需要Iterable中的对象:
it = values.iterator();
while (it.hasNext()) {
it.remove();
sum++;
}
小规模的基准测试没有显示出太多的性能差异,这个问题的任何评论或其他想法?
答案 0 :(得分:103)
TL; DR:使用优质Iterables.size(Iterable)
库的实用方法Guava。
在你的两个代码片段中,你应该使用第一个代码片段,因为第二个代码片段将删除values
中的所有元素,因此它之后是空的。更改像其大小这样的简单查询的数据结构是非常意外的。
对于性能,这取决于您的数据结构。如果它实际上是一个ArrayList
,从头开始删除元素(你的第二个方法正在做什么)是非常慢的(计算大小变为O(n * n)而不是O(n),因为它应该定)。
一般情况下,如果values
实际上只有Collection
而不仅仅是Iterable
,请检查此项并在以下情况下致电size()
:
if (values instanceof Collection<?>) {
return ((Collection<?>)values).size();
}
// use Iterator here...
对size()
的调用通常比计算元素数量要快得多,这个技巧正是Iterables.size(Iterable)
Guava为你做的。
答案 1 :(得分:34)
如果您使用的是Java 8,可以使用:
Iterable values = ...
long size = values.spliterator().getExactSizeIfKnown();
仅当可迭代源具有确定的大小时才会起作用。大多数收藏的Spliterator都会,但如果它来自HashSet
或ResultSet
,则可能会遇到问题。
您可以查看javadoc here.
如果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;
}
答案 2 :(得分:13)
这可能有点晚了,但可能对某人有所帮助。我在代码库中遇到Iterable
的类似问题,解决方案是使用for each
而不显式调用values.iterator();
。
int size = 0;
for(T value : values) {
size++;
}
答案 3 :(得分:6)
严格来说,Iterable没有大小。认为数据结构就像一个循环。
考虑关注Iterable实例,没有大小:
new Iterable(){
@Override public Iterator iterator() {
return new Iterator(){
@Override
public boolean hasNext() {
return isExternalSystemAvailble();
}
@Override
public Object next() {
return fetchDataFromExternalSystem();
}};
}};
答案 4 :(得分:5)
您可以将您的iterable转换为列表,然后在其上使用.size()。
Lists.newArrayList(iterable).size();
为清楚起见,上述方法需要进行以下导入:
import com.google.common.collect.Lists;
答案 5 :(得分:2)
我会选择it.next()
,原因很简单,next()
可以保证实施,而remove()
是可选操作。
E next()
返回迭代中的下一个元素。
void remove()
从底层集合中移除迭代器(可选操作)返回的最后一个元素。
答案 6 :(得分:0)
至于我,这些只是不同的方法。第一个离开你正在迭代的对象,而秒则将它留空。 问题是你想做什么。 删除的复杂性基于可迭代对象的实现。 如果你正在使用收藏 - 只需获得像Kazekage Gaara所提出的那样大小 - 它通常是性能最好的方法。
答案 7 :(得分:0)
java 8及更高版本
StreamSupport.stream(data.spliterator(), false).count();
答案 8 :(得分:-2)
为什么不在size()
上使用Collection
方法获取元素数量?
Iterator
只是为了迭代,没有别的。
答案 9 :(得分:-3)
我们可以简单地在ArrayList中对迭代进行类型转换并获取其大小,而不是使用循环并计算每个元素或使用第三方库。
new Row(
children: <Widget>[
new Flexible(child: new Text("Babe"), flex: 1,),
new Flexible(child: new Text("I miss you"), flex: 1,)
],
)