简体   繁体   English

Java和C ++中的迭代器有什么区别?

[英]What is the difference between iterators in Java and C++?

Java中Iterator的实现与C ++中的实现有何不同?

In the current C++ (98) standard library (in particular the portion formerly known as STL) defines a form of iterators that are very close to C pointers (including arithmetic). 在当前的C ++(98)标准库(特别是以前称为STL的部分)中定义了一种非常接近C指针(包括算术)的迭代器形式。 As such they just point somewhere. 因此他们只是指向某个地方。 To be useful, you generally need two pointers so that you can iterate between them. 为了有用,您通常需要两个指针,以便您可以在它们之间进行迭代。 I understand C++0x introduces ranges which act more like Java iterators. 我理解C ++ 0x引入的范围更像Java迭代器。

Java introduced the Iterator (and ListIterator ) interface in 1.2, largely taking over from the more verbose Enumerable. Java在1.2中引入了Iterator (和ListIterator )接口,主要接管了更详细的Enumerable。 Java has no pointer arithmetic, so there is no need to behave like a pointer. Java没有指针算术,因此不需要像指针一样工作。 They have a hasNext method to see if they have go to the end, instead of requiring two iterators. 他们有一个hasNext方法来查看它们是否已经结束,而不是需要两个迭代器。 The downside is that they are less flexible. 缺点是它们不够灵活。 The system requires methods as subList rather than iterating between two iterators are specific points in the containing list. 系统需要方法作为subList而不是在两个迭代器之间迭代是包含列表中的特定点。

A general difference in style is that whereas C++ use "static polymorphism" through templates, Java uses interfaces and the common dynamic polymorphism. 风格的一般差异是,虽然C ++通过模板使用“静态多态”,但Java使用接口和常见的动态多态。

The concept of iterators is to provide the glue to allow separation of "algorithm" (really control flow) and data container. 迭代器的概念是提供粘合剂以允许分离“算法”(真正的控制流)和数据容器。 Both approaches do that reasonably well. 两种方法都做得相当好。 In ideal situations "normal" code should barely see iterators. 在理想情况下,“普通”代码几乎不应该看到迭代器。

C++ doesn't specify how iterators are implemented. C ++没有指定迭代器的实现方式。 It does however specify their interface and the minimal behaviour they must provide in order to work with other Standard Library components. 但它确实指定了它们的接口以及它们必须提供的最小行为才能使用其他标准库组件。

For example, for input iterators, the Standard specifies that an iterator must be dereferenceable via the * operator. 例如,对于输入迭代器,标准指定必须通过*运算符解除引用迭代器。 It does not however specify how that operator is to be implemented. 但是,它没有说明如何实施该运营商。

In C++, you see people passing around iterators all the time. 在C ++中,您会看到人们一直在传递迭代器。 C++ iterators "point" to a specific element of a container. C ++迭代器“指向”容器的特定元素。 You can dereference an iterator to get the element (and you can do this over and over). 您可以取消引用迭代器来获取元素(并且您可以反复执行此操作)。 You can erase the element that an iterator refers to efficiently. 您可以有效地擦除迭代器引用的元素。 You can also make copies of an iterator (either by assigning to another variable, or passing an iterator by value to a function) to keep track of multiple places at the same time. 您还可以复制迭代器(通过分配给另一个变量,或者通过值将迭代器传递给函数)来同时跟踪多个位置。 Iterators in C++ can become "invalidated" by certain operations on the container, depending on the container. C ++中的迭代器可能会因容器上的某些操作而“无效”,具体取决于容器。 When an iterator becomes invalidated (the rules of which might be complex), operations with the iterator have undefined behavior, and may (inconsistently) crash your program or return incorrect results; 当迭代器变为无效(其规则可能很复杂)时,使用迭代器的操作具有未定义的行为,并且可能(不一致地)使程序崩溃或返回不正确的结果; although in some data structures (eg std::list ), iterators remain valid through most modifications of the container. 虽然在某些数据结构中(例如std::list ),迭代器通过容器的大多数修改仍然有效。

In Java, you don't see that kind of usage. 在Java中,您没有看到这种用法。 An Iterator in Java points "between" two elements, rather than "at" an element. Java中的迭代器指向“两个”元素之间,而不是“在”一个元素。 The only way you get elements with an iterator is to move it forwards to get the element you moved over. 使用迭代器获取元素的唯一方法是将其向前移动以获取移动的元素。 Of course that changes the state of the iterator, and you can't go back; 当然,这会改变迭代器的状态,你不能回头; unless you have a ListIterator in which case you can move both forwards and backwards (but it is still annoying to have to move forwards and backwards just to remain still). 除非你有一个ListIterator在这种情况下你可以向前和向后移动(但是为了保持静止而必须向前和向后移动仍然很烦人)。 You can't copy an iterator, because the interface does not expose a public copy method; 您无法复制迭代器,因为该接口不公开公共复制方法; so for example, you can't just pass a marker of a specific location to a function, without giving that function a reference to the same iterator that you have, and thereby allowing them to change the state of your iterator. 因此,例如,您不能只将特定位置的标记传递给函数,而不必为该函数提供对同一迭代器的引用,从而允许它们更改迭代器的状态。 In Java, an iterator will be invalidated (at least in the standard containers) by any modification of the container except through the iterator's own add() or remove() methods, which is overly conservative (eg most modifications on a LinkedList should not affect an iterator). 在Java中,迭代器将通过容器的任何修改而无效(至少在标准容器中),除非通过迭代器自己的add()remove()方法,这是过于保守的(例如, LinkedList上的大多数修改不应该影响一个迭代器)。 When you try to use an invalidated iterator, it raises ConcurrentModificationException (confusingly named because it has nothing to do with Concurrency) instead of possibly causing undefined behavior, which is good. 当您尝试使用无效的迭代器时,它会引发ConcurrentModificationException (由于它与Concurrency无关而引起混淆),而不是可能导致未定义的行为,这很好。

C++ iterators (STL) try to mimic pointer syntax as much as possible, through operator overloading. C ++迭代器(STL)尝试通过运算符重载尽可能地模仿指针语法。

The standard specification define the various iterator concepts (like forward, bidirectional, random access, input, output). 标准规范定义了各种迭代器概念(如前向,双向,随机访问,输入,输出)。 Each concept should match a specific interface (eg ++ operator for forward iterator to go to the next element in sequence, -- for bidirectional, +, += for random access, etc). 每个概念应该与特定接口匹配(例如,用于转发迭代器的++运算符以按顺序转到下一个元素, - 用于双向,+,+ =用于随机访问等)。

implementations are defined entirely by standard library vendors/JRE vendors in C++/Java respectively. 实现完全由C ++ / Java中的标准库供应商/ JRE供应商定义。 They are free to implement them however they want, as long as their behaviour conforms to the respective standards. 只要他们的行为符合各自的标准,他们就可以随意实施。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM