Yineleyicinin sayısını almanın "sayısal olarak" hızlı bir yolu var mı?
int i = 0;
for ( ; some_iterator.hasNext() ; ++i ) some_iterator.next();
... CPU döngülerinin boşa harcanması gibi görünüyor.
Yineleyicinin sayısını almanın "sayısal olarak" hızlı bir yolu var mı?
int i = 0;
for ( ; some_iterator.hasNext() ; ++i ) some_iterator.next();
... CPU döngülerinin boşa harcanması gibi görünüyor.
to provide an implementation-independent method for access, in which the user does not need to know whether the underlying implementation is some form of array or of linked list, and allows the user go through the collection without explicit indexing. penguin.ewu.edu/~trolfe/LinkedSort/Iterator.html
Yanıtlar:
Yineleyiciyi yeni aldıysanız, yapmanız gereken şey budur - yinelemek için kaç öğe kaldığını bilmez , bu nedenle bu sonucu sorgulayamazsınız. Bunu yapacak gibi görünen yardımcı yöntemler vardır ( Iterators.size()Guava'da olduğu gibi ), ancak bunların altında yaklaşık olarak aynı işlemi gerçekleştiriyorlar.
Ancak birçok yineleyici, genellikle boyutlarını sorgulayabileceğiniz koleksiyonlardan gelir. Yineleyiciyi aldığınız kullanıcı tarafından oluşturulmuş bir sınıfsa, bu sınıfta bir size () yöntemi sağlamaya çalışabilirsiniz.
Kısacası, yalnızca yineleyiciye sahip olduğunuz durumda daha iyi bir yol yoktur, ancak boyutu doğrudan alabileceğiniz temel koleksiyona veya nesneye erişebilmenizden çok daha fazlası yoktur.
Iterators.size(...)aşağıdaki diğer yorumlarda ve java-doc'ta bahsedilmiştir): "Yineleyicide kalan öğelerin sayısını döndürür. Yineleyici bitmiş olarak bırakılır: hasNext () yöntemi yanlış döndürür." Bu, daha sonra Yineleyiciyi kullanamayacağınız anlamına gelir. Lists.newArrayList(some_iterator);yardımcı olabilir.
Guava kitaplığını kullanarak :
int size = Iterators.size(iterator);
Dahili olarak, sadece kolaylık sağlamak için tüm öğeleri yineler.
Kodunuz, yineleyicinin sonuna geldiğinizde size bir istisna verecektir. Yapabilirsin:
int i = 0;
while(iterator.hasNext()) {
i++;
iterator.next();
}
Altta yatan koleksiyona erişiminiz olsaydı, arayabilirdiniz coll.size()...
DÜZENLE TAMAM, değiştirdiniz ...
Her zaman yinelemeniz gerekecek. Yine de sayımı açıkça döngü yapmadan yapmak için Java 8, 9'u kullanabilirsiniz:
Iterable<Integer> newIterable = () -> iter;
long count = StreamSupport.stream(newIterable.spliterator(), false).count();
İşte bir test:
public static void main(String[] args) throws IOException {
Iterator<Integer> iter = Arrays.asList(1, 2, 3, 4, 5).iterator();
Iterable<Integer> newIterable = () -> iter;
long count = StreamSupport.stream(newIterable.spliterator(), false).count();
System.out.println(count);
}
Bu şunu yazdırır:
5
Yeterince ilginç olan parallel, bu çağrıdaki bayrağı değiştirerek burada sayma işlemini paralel hale getirebilirsiniz :
long count = StreamSupport.stream(newIterable.spliterator(), *true*).count();
Guava kitaplığını kullanarak , başka bir seçenek, Iterablebir List.
List list = Lists.newArrayList(some_iterator);
int count = list.size();
Boyutunu aldıktan sonra yineleyicinin öğelerine de erişmeniz gerekiyorsa bunu kullanın. Iterators.size()Sizi kullanarak yinelenen öğelere artık erişemezsiniz.
Sahip olduğunuz tek şey yineleyici ise, o zaman hayır, "daha iyi" bir yol yoktur. Yineleyici bir koleksiyondan geliyorsa, boyut için bunu yapabilirsiniz.
Yineleyicinin yalnızca farklı değerleri geçmek için bir arayüz olduğunu unutmayın, bunun gibi bir koda sahip olursunuz.
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");
}
};
veya
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");
}
};
Sahip olduğunuz tek şey yineleyiciyse, daha verimli bir yol yoktur. Ve yineleyici yalnızca bir kez kullanılabiliyorsa, yineleyicinin içeriğini almadan önce sayımı almak ... sorunludur.
Çözüm, sayıma ihtiyaç duymaması için uygulamanızı değiştirmek veya sayımı başka yollarla elde etmektir. (Örneğin, ... Collectionyerine a iletin Iterator)
yineleyici nesnesi, koleksiyonunuzun içerdiği aynı sayıda öğeyi içerir.
List<E> a =...;
Iterator<E> i = a.iterator();
int size = a.size();//Because iterators size is equal to list a's size.
Ancak yineleyicinin boyutunu almak ve dizin 0 aracılığıyla bu boyuta yinelemek yerine, yineleyicinin next () yöntemini yinelemek daha iyidir .
a, ama sadece i?