簡體   English   中英

C++ (stl) 和 Java 中的迭代器,在概念上有區別嗎?

[英]Iterators in C++ (stl) vs Java, is there a conceptual difference?

在離開了一段時間並試圖清除舊瓜后,我將回到 C++。

在 Java 中,迭代器是容器的接口,具有以下方法: hasNext()next()remove() hasNext()的存在意味着它具有對正在遍歷的容器的限制的概念

//with an Iterator
Iterator<String> iter = trees.iterator();
while (iter.hasNext()) 
{
    System.out.println(iter.next());
}

在 C++ 標准模板庫中,迭代器似乎表示支持operator++operator==的數據類型或類,但沒有內置限制的概念,因此在前進到下一項之前需要進行比較。 在正常情況下,用戶必須通過比較兩個迭代器來檢查限制,第二個迭代器是容器端。

vector<int> vec;
vector<int>::iterator iter;

// Add some elements to vector
v.push_back(1);
v.push_back(4);
v.push_back(8);

for (iter= v.begin(); iter != v.end(); iter++)
{
    cout << *i << " "; //Should output 1 4 8
}

有趣的是,在 C++ 中,指針是指向數組的迭代器。 STL 采用了現有的內容並圍繞它建立了約定。

我想念的還有什么更微妙的地方嗎?

也許更理論化一點。 在數學上,C++ 中的集合可以描述為迭代器的半開區間,即一個迭代器指向集合的開頭,一個迭代器指向最后一個元素的后面

這個約定開辟了許多可能性。 算法在 C++ 中的工作方式,它們都可以應用於更大集合的子序列。 要在 Java 中實現這樣的功能,您必須圍繞現有集合創建一個包裝器,該集合返回不同的迭代器。

Frank 已經提到了迭代器的另一個重要方面。 迭代器有不同的概念。 Java迭代器對應於C++的輸入迭代器,即只讀迭代器,一次只能遞增一步,不能倒退。

在另一個極端,您有 C 指針,它們與 C++ 的隨機訪問迭代器概念完全對應。

總而言之,與 C 指針或 Java 迭代器相比,C++ 提供了更豐富、更純粹的概念,可以應用於更廣泛的任務。

是的,存在很大的概念差異。 C++ 使用不同的迭代器“類”。 有些用於隨機訪問(與 Java 不同),有些用於前向訪問(如 java)。 甚至其他人也用於寫入數據(例如用於transform )。

請參閱C++ 文檔中的迭代器概念:

  • 輸入迭代器
  • 輸出迭代器
  • 前向迭代器
  • 雙向迭代器
  • 隨機訪問迭代器

與 Java/C# 的微不足道的迭代器相比,這些更有趣和強大。 希望這些約定將使用 C++0x 的Concepts進行編纂。

如前所述,Java 和 C# 迭代器描述了一個混合的位置(狀態)和范圍(值),而 C++ 迭代器將位置和范圍的概念分開。 C++ 迭代器分別代表“我現在在哪里”和“我可以去哪里?”。

無法復制 Java 和 C# 迭代器。 您無法恢復以前的位置。 常見的 C++ 迭代器可以。

考慮這個例子

// for each element in vec
for(iter a = vec.begin(); a != vec.end(); ++a){
  // critical step!  We will revisit 'a' later.
  iter cur = a; 
  unsigned i = 0;
  // print 3 elements
  for(; cur != vec.end() && i < 3; ++cur, ++i){
      cout << *cur << " ";
  }
  cout << "\n";
}

單擊上面的鏈接查看程序輸出。

這個相當愚蠢的循環遍歷一個序列(僅使用前向迭代器語義),打印 3 個元素的每個連續子序列一次(以及最后幾個較短的子序列)。 但是假設 N 個元素,每行 M 個元素而不是 3 個,這個算法仍然是 O(N*M) 迭代器增量和 O(1) 空間。

Java 風格的迭代器缺乏獨立存儲位置的能力。 你要么

  • 丟失 O(1) 空間,使用(例如)大小為 M 的數組在迭代時存儲歷史記錄
  • 將需要遍歷列表 N 次,使 O(N^2+N*M) 時間
  • 或者使用具有 GetAt 成員函數的具體 Array 類型,失去通用性和使用鏈表容器類型的能力。

由於只有向前迭代機制,在此例子中,我能交換與名單沒有問題 這對於編寫通用算法至關重要,例如搜索、延遲初始化和評估、排序等。

無法保持狀態最接近於 C++ STL 輸入迭代器,在其上構建的算法很少。

指向數組元素的指針實際上是數組的迭代器。

正如您所說,在 Java 中,迭代器比 C++ 對底層容器有更多的了解。 C++ 迭代器是通用的,一迭代器可以表示任何范圍:這可以是一個容器的子范圍,一個跨多個容器的范圍(參見http://www.justsoftwaresolutions.co.uk/articles/pair_iterators.pdfhttp://www.boost.org/doc/libs/1_36_0/libs/iterator/doc/zip_iterator.html )甚至一系列數字(參見http://www.boost.org/doc/libs/1_36_0 /libs/iterator/doc/counting_iterator.html )

迭代器類別標識您可以使用給定的迭代器做什么和不能做什么。

對我來說,根本的區別在於 Java 迭代器指向項之間,而 C++ STL 迭代器指向項。

關於差異有很多很好的答案,但我覺得 Java 迭代器最讓我煩惱的事情沒有被強調——你不能多次讀取當前值。 這在很多場景中非常有用,尤其是在合並迭代器時。

在 C++ 中,您有一個方法來推進迭代器並讀取當前值。 讀取它的值不會推進迭代; 所以你可以多次閱讀它。 這對於 Java 迭代器是不可能的,我最終創建了執行此操作的包裝器。

旁注:創建包裝器的一種簡單方法是使用現有的包裝器——來自 Guava 的PeekingIterator

C++ 迭代器是指針概念的概括; 它們使其適用於更廣泛的情況。 這意味着它們可以用來做諸如定義任意范圍之類的事情。

Java 迭代器是相對愚蠢的枚舉器(雖然不像 C# 那樣糟糕;至少 Java 有 ListIterator 並且可以用來改變集合)。

在按順序迭代數組內容的平凡情況下,迭代器僅等效於指針。 迭代器可以從任意數量的其他來源提供對象:來自數據庫、文件、網絡、其他一些計算等。

C++ 庫(以前稱為 STL 的部分)迭代器旨在與指針兼容。 Java,沒有指針算法,可以自由地對程序員更友好。

在 C++ 中,您最終不得不使用一對迭代器。 在 Java 中,您可以使用迭代器或集合。 迭代器應該是算法和數據結構之間的粘合劑。 為 1.5+ 編寫的代碼很少需要提及迭代器,除非它正在實現特定的算法或數據結構(大多數程序員不需要這樣做)。 由於 Java 使用動態多態性子集等,因此更容易處理。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM