英文:
Does the Internal Iterator use the hasNext() and next() to iterate in Java?
问题
我正在学习内部迭代器,我明白内部迭代器在后台管理迭代:
public void internalIterator(){
List<String> namesList = Arrays.asList("Tom", "Dick", "Harry");
namesList.forEach(name -> System.out.println(name));
}
但我认为增强型for循环做的事情相同:
public void enhancedForLoop(){
List<String> namesList = Arrays.asList("Tom", "Dick", "Harry");
for(String name : namesList){
System.out.println(name);
}
}
我知道增强型for循环在后台使用hasNext()
和next()
方法。而增强型for循环是外部迭代器。那么为什么forEach()
方法是内部迭代器呢?forEach()
方法不也在后台使用hasNext()
和next()
方法吗?迭代是如何以不同于增强型for循环的方式在后台管理的呢?并且使用forEach()
比使用增强型for循环更快吗?任何反馈将不胜感激。
英文:
I'm learning about internal iterators and I understand that an internal iterator manage the iterations in the background:
public void internalIterator(){
List<String> namesList = Arrays.asList("Tom", "Dick", "Harry");
namesList.forEach(name -> System.out.println(name));
}
But I think that enhanced for loop does the same thing:
public void enhancedForLoop(){
List<String> namesList = Arrays.asList("Tom", "Dick", "Harry");
for(String name : namesList){
System.out.println(name);
}
}
I know that enhanced for loop uses hasNext() and next() methods in the background. And enhanced for loop is an external iterator. Then why forEach() method is an internal iterator? Doesn't forEach() method use hasNext() and next() methods in the background? How the iterations are managed in the backgorund in a different way than enhanced for loop? And is the iteration faster using forEach() than using enhanced for loop? Any feedback will be apreciated?
答案1
得分: 2
参见接口 Iterable
上 forEach
的定义。
这两种构造使用同一接口的不同方法。
从概念上讲,“增强型 for 循环”中实现 Iterable
接口的类仅创建 Iterator
,循环结构负责推进它(还可参见此相关问题)。
在调用 forEach
时,类控制整个迭代过程,并且可以根据其底层数据结构选择最合适的方式。例如,它可以避免创建 Iterator
对象,而是使用一些内部数组索引或类似的东西。
除此之外,它们应该是等效的。在大多数情况下,我不会预期任何性能差异。
参见这个优秀的回答,了解一些使用 forEach
的额外原因,例如在迭代同步集合时提供的附加一致性保证,以及这个回答提到它不提供的内容,比如流控制(例如使用 break
进行短路)或支持已检查异常。
英文:
See also the definition of forEach
on the interface Iterable
.
Both constructs use different methods of the same interface.
Conceptually, the difference is that in an "enhanced for loop" the class implementing the Iterable
only creates the Iterator
, and the loop construct is responsible for advancing it (see also this related question).
When calling forEach
, the class controls the entire process of iteration, and can pick whatever is most suitable for its underlying data structure. For example, it could avoid creating an Iterator
object, and instead use some internal array index or similar.
Other than that, they should be equivalent. In most cases I wouldn't expect any difference in performance.
See this excellent answer for some additional reasons why you might want to use forEach
, e.g. additional consistency guarantees when iterating synchronized collections, and this one mentioning things that it does not provide, such as flow control (e.g. short-circuiting using break
) or support for checked exceptions.
答案2
得分: 1
Differences
外部
在使用iterator()
时,用户(您)需要管理遍历的过程:何时调用hasNext()
以及何时调用next()
。迭代是由API的用户外部处理的。用户同时遍历元素并消耗这些元素。
内部
在使用forEach
时,API负责管理遍历过程。迭代由API内部处理,而不是由用户处理;用户只消耗元素。
结论
hasNext()
和next()
是否被调用并不重要。重要的是由谁调用hasNext()
和next()
- 谁处理迭代,谁负责迭代器。
forEach
是内部的,因为用户无法控制元素的迭代方式。API处理这一切;迭代器是内部的。
iterator()
是外部的,因为用户必须定义迭代的方式。API将迭代器传递给您,这就是API的全部工作。迭代器是外部的。
即使forEach
在某些情况下使用iterator()
,该迭代器仍然是您使用的API(List
)内部的。调用forEach
的人仍然只需担心消耗元素。用户不控制元素的遍历方式,因此forEach
使用什么并不重要。
在何时使用不同策略的建议
当您需要最基本的顺序迭代时,可以使用增强型循环。
当您需要更复杂的迭代时,可以使用iterator()
。
当您只关心消耗元素,不介意API决定如何遍历集合时,可以使用forEach
。
英文:
The difference is what the user of the API has to do.
Differences
External
When using iterator()
, it's the user's job (your job) to manage the traversal: when to call hasNext()
and when to call next()
. The iteration is handled externally from the API, by the user of the API. The user both iterates through the elements & consumes the elements.
Internal
When using forEach
, it's the API's job to manage the traversal. The iteration is handled internally instead of by the user; the user only consumes the elements.
Conclusion
It doesn't matter if hasNext()
and next()
are being called. What does matter is who calls hasNext()
and next()
- who handles the iteration, who is in charge of the iterator.
forEach
is internal because the user doesn't have control over how the elements are iterated through. The API handles it; the iterator is internal.
iterator()
is external because the user must define how iteration will occur. The API passes you the iterator, and that's all the API does. The iterator is external.
Even though forEach
uses iterator()
in some cases, that iterator is still internal to the API you're using (the List
). Whoever calls forEach
still only worry about consuming elements. The user doesn't control how the elements are traversed through, so it doesn't matter what forEach
uses.
Suggestions on when to use a strategy
You'd use an enhanced loop when you need the most basic of sequential iteration.
You'd use an iterator()
when you need more complex iteration.
You'd use forEach
when you're only worried about consuming the elements, and don't mind if the API decides on how to traverse through the collection.
答案3
得分: -1
我不知道你从哪里得到那个"增强型for循环是外部迭代器"的观点,但是Iterable.forEach
方法实际上与你的第二个示例做的事情是相同的(虽然可以被重写,但我并没有看到任何理由去这么做)。
default void forEach(Consumer<? super T> action) {
Objects.requireNonNull(action);
for (T t : this) {
action.accept(t);
}
}
英文:
I don't know where you got that "enhanced for loop is an external iterator", but Iterable.forEach
just does the same thing as your second example (could be overridden, though I don't see any reason to).
default void forEach(Consumer<? super T> action) {
Objects.requireNonNull(action);
for (T t : this) {
action.accept(t);
}
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论