Есть ли "вычислительный" быстрый способ получить счетчик итератора?
int i = 0;
for ( ; some_iterator.hasNext() ; ++i ) some_iterator.next();
... кажется пустой тратой циклов процессора.
Есть ли "вычислительный" быстрый способ получить счетчик итератора?
int i = 0;
for ( ; some_iterator.hasNext() ; ++i ) some_iterator.next();
... кажется пустой тратой циклов процессора.
Если вы только что получили итератор, то что вам нужно будет сделать - он не знает, сколько элементов осталось, чтобы перебрать, поэтому вы не можете запросить его для этого результата.
Однако многие итераторы поступают из коллекций, которые вы часто можете запрашивать по их размеру. И если это пользовательский класс, на который вы получаете итератор, вы можете посмотреть, как предоставить метод size() для этого класса.
Короче говоря, в ситуации, когда у вас есть только итератор, тогда нет лучшего способа, но гораздо чаще, чем нет, у вас есть доступ к базовой коллекции или объекту, из которого вы можете получить размер напрямую.
Использование библиотеки Guava:
int size = Iterators.size(iterator);
Внутри он просто выполняет итерации по всем элементам, поэтому просто для удобства.
Ваш код даст вам исключение, когда вы достигнете конца итератора. Вы можете сделать:
int i = 0;
while(iterator.hasNext()) {
i++;
iterator.next();
}
Если у вас был доступ к основной коллекции, вы могли бы вызвать coll.size()
...
ИЗМЕНИТЬ ОК вы внесли поправки...
Нет лучшего способа, если все, что у вас есть, это итератор.
Решение состоит в том, чтобы изменить ваше приложение, чтобы оно не нуждалось в подсчете, или получить его каким-либо другим способом. (Например, передайте Collection
, а не Iterator
...)
Если у вас есть итератор, то нет, нет "лучшего" способа. Если итератор поступает из коллекции, вы могли бы как это сделать для размера.
Имейте в виду, что Iterator - это просто интерфейс для прохождения различных значений, у вас будет очень хороший код, например
new Iterator<Long>() {
final Random r = new Random();
@Override
public boolean hasNext() {
return true;
}
@Override
public Long next() {
return r.nextLong();
}
@Override
public void remove() {
throw new IllegalArgumentException("Not implemented");
}
};
или
new Iterator<BigInteger>() {
BigInteger next = BigInteger.ZERO;
@Override
public boolean hasNext() {
return true;
}
@Override
public BigInteger next() {
BigInteger current = next;
next = next.add(BigInteger.ONE);
return current;
}
@Override
public void remove() {
throw new IllegalArgumentException("Not implemented");
}
};
Другой вариант - преобразовать Iterable
в List
.
int count = Lists.newArrayList(some_iterator).size();
Объект итератора содержит то же количество элементов, что и ваша коллекция.
List<E> a =...;
Iterator<E> i = a.iterator();
int size = a.size();//Because iterators size is equal to list a size.
Но вместо того, чтобы получать размер итератора и итерации с помощью индекса 0 до этого размера, лучше выполнить итерацию с помощью метода next() итератора.