2012-03-15 88 views
61

是否有一種「計算上」的快速方法來獲得迭代器的計數?獲得迭代器的數量/長度/大小的最佳方式是什麼?

int i = 0; 
for (; some_iterator.hasNext() ; ++i) some_iterator.next(); 

...似乎是浪費CPU週期。

+2

迭代器不一定對應於具有「count」的東西... – 2012-03-15 13:01:05

+0

迭代器是它們是什麼;迭代到集合中的下一個對象(它可以是set,array等任何東西)爲什麼當他們不關心他們想要迭代的內容時,他們需要告訴大小? '爲訪問提供獨立於實現的方法,其中用戶不需要知道底層實現是某種形式的數組還是鏈接列表,並且允許用戶在沒有明確索引的情況下瀏覽集合。 /penguin.ewu.edu/~trolfe/LinkedSort/Iterator.html – ecle 2012-03-15 13:01:42

回答

52

如果你拿到的迭代器那麼這是你必須做的 - 它不知道它有多少項目就剩到迭代,所以你不能查詢它的結果。

但是,許多迭代器來自集合,您可以經常查詢它們的大小。如果它是一個用戶創建的類,您將獲得迭代器,您可以在該類上提供size()方法。

簡而言之,在只有有迭代器的情況下,沒有更好的方法,但更多的情況是您可以訪問底層集合或對象,從中可以直接獲取大小。

4

沒有更有效的方法,如果你擁有的只是迭代器。如果迭代器只能使用一次,那麼在獲取迭代器的內容之前獲取計數是有問題的。

解決方案是更改您的應用程序,使其不需要計數或通過其他方式獲取計數。 (例如,通過一個Collection而非Iterator ...)

7

當你到達迭代器的末尾時,你的代碼會給你一個異常。你可以這樣做:

int i = 0; 
while(iterator.hasNext()) { 
    i++; 
    iterator.next(); 
} 

如果你有機會訪問底層集合,你就可以打電話coll.size() ......

編輯 確定你已經修改了...

-3

迭代器對象包含與您的集合包含的元素相同數量的元素。

List<E> a =...; 
Iterator<E> i = a.iterator(); 
int size = a.size();//Because iterators size is equal to list a's size. 

而是獲得迭代器的尺寸,並通過索引0迭代到規定大小,最好是通過該方法的迭代器的下()進行迭代。

+0

如果我們沒有'a',但只有'i',該怎麼辦? – Tvde1 2017-09-25 08:47:52

5

如果你擁有的只是迭代器,那麼不,沒有「更好」的方法。如果迭代器來自一個集合,那麼可以按照大小進行設置。

請記住,迭代器就是爲穿越不同值的界面,你會很好得如下代碼

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"); 
     } 
    }; 
71

使用Guava library

int size = Iterators.size(iterator); 

內部它只是遍歷所有元素,所以它只是爲了方便。

4

另一種選擇是將Iterable轉換爲List

int count = Lists.newArrayList(some_iterator).size(); 
+1

它有多少效率? – LoveToCode 2016-04-27 12:55:48

+2

@LoveToCode比原始問題上的例子效率低 – Winter 2016-12-20 17:44:41

+2

當然,創建一個包含所有元素的新對象比迭代和丟棄要慢。恕我直言,這個解決方案是一個提高代碼可讀性的單線程。我使用它很多元素(高達1000)或速度不是問題的集合。 – tashuhka 2016-12-21 10:05:23

2

您將始終需要迭代。然而,你可以使用Java 8,9做計數沒有明確地循環:

Iterable<Integer> newIterable =() -> iter; 
long count = StreamSupport.stream(newIterable.spliterator(), false).count(); 

下面是測試:

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); 
} 

此打印:

5 

足夠有趣,你可以並行通過更改此通話中的parallel標誌來計數操作:

long count = StreamSupport.stream(newIterable.spliterator(), *true*).count(); 
相關問題