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

时间:2022-09-01 11:31:31

How is the implementation of Iterator in Java different from that in C++?

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

5 个解决方案

#1


8  

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). 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 ++(98)标准库(特别是以前称为STL的部分)中定义了一种非常接近C指针(包括算术)的迭代器形式。因此他们只是指向某个地方。为了有用,您通常需要两个指针,以便您可以在它们之间进行迭代。我理解C ++ 0x引入的范围更像Java迭代器。

Java introduced the Iterator (and ListIterator) interface in 1.2, largely taking over from the more verbose Enumerable. Java has no pointer arithmetic, so there is no need to behave like a pointer. They have a hasNext method to see if they have go to the end, instead of requiring two iterators. 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.

Java在1.2中引入了Iterator(和ListIterator)接口,主要取代了更详细的Enumerable。 Java没有指针算法,因此不需要像指针一样运行。他们有一个hasNext方法来查看它们是否已经结束,而不是需要两个迭代器。缺点是它们不够灵活。系统需要方法作为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.

迭代器的概念是提供粘合剂以允许“算法”(真正的控制流)和数据容器的分离。两种方法都做得相当好。在理想情况下,“普通”代码几乎不应该看到迭代器。

#2


6  

C++ doesn't specify how iterators are implemented. It does however specify their interface and the minimal behaviour they must provide in order to work with other Standard Library components.

C ++没有指定迭代器的实现方式。但它确实指定了它们的接口以及它们必须提供的最小行为才能使用其他标准库组件。

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.

例如,对于输入迭代器,标准指定必须通过*运算符解除引用迭代器。但是,它没有说明如何实施该运营商。

#3


2  

In C++, you see people passing around iterators all the time. C++ iterators "point" to a specific element of a container. 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. 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 (e.g. std::list), iterators remain valid through most modifications of the container.

在C ++中,您会看到人们一直在传递迭代器。 C ++迭代器“指向”容器的特定元素。您可以取消引用迭代器来获取元素(并且您可以反复执行此操作)。您可以有效地擦除迭代器引用的元素。您还可以创建迭代器的副本(通过分配给另一个变量,或者通过值将迭代器传递给函数)来同时跟踪多个位置。 C ++中的迭代器可能会因容器上的某些操作而“无效”,具体取决于容器。当迭代器失效(其规则可能很复杂)时,使用迭代器的操作具有未定义的行为,并且可能(不一致地)使程序崩溃或返回不正确的结果;虽然在某些数据结构中(例如std :: list),迭代器通过容器的大多数修改仍然有效。

In Java, you don't see that kind of usage. An Iterator in Java points "between" two elements, rather than "at" an element. 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). 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 (e.g. most modifications on a LinkedList should not affect an iterator). 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.

在Java中,您没有看到这种用法。 Java中的迭代器指向“两个”元素之间,而不是“在”一个元素。使用迭代器获取元素的唯一方法是将其向前移动以获取移动的元素。当然,这会改变迭代器的状态,你不能回头;除非你有一个ListIterator,在这种情况下你可以向前和向后移动(但是为了保持静止而必须向前和向后移动仍然很烦人)。您无法复制迭代器,因为该接口不公开公共复制方法;因此,例如,您不能只将特定位置的标记传递给函数,而不必为该函数提供对同一迭代器的引用,从而允许它们更改迭代器的状态。在Java中,迭代器将通过容器的任何修改而无效(至少在标准容器中),除非通过迭代器自己的add()或remove()方法,这是过于保守的(例如,LinkedList上的大多数修改都不应该影响迭代器)。当您尝试使用无效的迭代器时,它会引发ConcurrentModificationException(由于它与Concurrency无关而引起混淆),而不是可能导致未定义的行为,这很好。

#4


1  

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 (e.g. ++ operator for forward iterator to go to the next element in sequence, -- for bidirectional, +, += for random access, etc).

标准规范定义了各种迭代器概念(如前向,双向,随机访问,输入,输出)。每个概念应该与特定接口匹配(例如,用于转发迭代器的++运算符以按顺序转到下一个元素, - 用于双向,+,+ =用于随机访问等)。

#5


0  

implementations are defined entirely by standard library vendors/JRE vendors in C++/Java respectively. They are free to implement them however they want, as long as their behaviour conforms to the respective standards.

实现完全由C ++ / Java中的标准库供应商/ JRE供应商定义。只要他们的行为符合各自的标准,他们就可以随意实施。

#1


8  

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). 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 ++(98)标准库(特别是以前称为STL的部分)中定义了一种非常接近C指针(包括算术)的迭代器形式。因此他们只是指向某个地方。为了有用,您通常需要两个指针,以便您可以在它们之间进行迭代。我理解C ++ 0x引入的范围更像Java迭代器。

Java introduced the Iterator (and ListIterator) interface in 1.2, largely taking over from the more verbose Enumerable. Java has no pointer arithmetic, so there is no need to behave like a pointer. They have a hasNext method to see if they have go to the end, instead of requiring two iterators. 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.

Java在1.2中引入了Iterator(和ListIterator)接口,主要取代了更详细的Enumerable。 Java没有指针算法,因此不需要像指针一样运行。他们有一个hasNext方法来查看它们是否已经结束,而不是需要两个迭代器。缺点是它们不够灵活。系统需要方法作为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.

迭代器的概念是提供粘合剂以允许“算法”(真正的控制流)和数据容器的分离。两种方法都做得相当好。在理想情况下,“普通”代码几乎不应该看到迭代器。

#2


6  

C++ doesn't specify how iterators are implemented. It does however specify their interface and the minimal behaviour they must provide in order to work with other Standard Library components.

C ++没有指定迭代器的实现方式。但它确实指定了它们的接口以及它们必须提供的最小行为才能使用其他标准库组件。

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.

例如,对于输入迭代器,标准指定必须通过*运算符解除引用迭代器。但是,它没有说明如何实施该运营商。

#3


2  

In C++, you see people passing around iterators all the time. C++ iterators "point" to a specific element of a container. 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. 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 (e.g. std::list), iterators remain valid through most modifications of the container.

在C ++中,您会看到人们一直在传递迭代器。 C ++迭代器“指向”容器的特定元素。您可以取消引用迭代器来获取元素(并且您可以反复执行此操作)。您可以有效地擦除迭代器引用的元素。您还可以创建迭代器的副本(通过分配给另一个变量,或者通过值将迭代器传递给函数)来同时跟踪多个位置。 C ++中的迭代器可能会因容器上的某些操作而“无效”,具体取决于容器。当迭代器失效(其规则可能很复杂)时,使用迭代器的操作具有未定义的行为,并且可能(不一致地)使程序崩溃或返回不正确的结果;虽然在某些数据结构中(例如std :: list),迭代器通过容器的大多数修改仍然有效。

In Java, you don't see that kind of usage. An Iterator in Java points "between" two elements, rather than "at" an element. 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). 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 (e.g. most modifications on a LinkedList should not affect an iterator). 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.

在Java中,您没有看到这种用法。 Java中的迭代器指向“两个”元素之间,而不是“在”一个元素。使用迭代器获取元素的唯一方法是将其向前移动以获取移动的元素。当然,这会改变迭代器的状态,你不能回头;除非你有一个ListIterator,在这种情况下你可以向前和向后移动(但是为了保持静止而必须向前和向后移动仍然很烦人)。您无法复制迭代器,因为该接口不公开公共复制方法;因此,例如,您不能只将特定位置的标记传递给函数,而不必为该函数提供对同一迭代器的引用,从而允许它们更改迭代器的状态。在Java中,迭代器将通过容器的任何修改而无效(至少在标准容器中),除非通过迭代器自己的add()或remove()方法,这是过于保守的(例如,LinkedList上的大多数修改都不应该影响迭代器)。当您尝试使用无效的迭代器时,它会引发ConcurrentModificationException(由于它与Concurrency无关而引起混淆),而不是可能导致未定义的行为,这很好。

#4


1  

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 (e.g. ++ operator for forward iterator to go to the next element in sequence, -- for bidirectional, +, += for random access, etc).

标准规范定义了各种迭代器概念(如前向,双向,随机访问,输入,输出)。每个概念应该与特定接口匹配(例如,用于转发迭代器的++运算符以按顺序转到下一个元素, - 用于双向,+,+ =用于随机访问等)。

#5


0  

implementations are defined entirely by standard library vendors/JRE vendors in C++/Java respectively. They are free to implement them however they want, as long as their behaviour conforms to the respective standards.

实现完全由C ++ / Java中的标准库供应商/ JRE供应商定义。只要他们的行为符合各自的标准,他们就可以随意实施。