問題描述
我在一次采訪中被問到使用迭代器比 for
循環有什么優勢,或者使用 for
循環比迭代器有什么優勢?
I was asked in an interview what is the advantage of using iterator over for
loop or what is the advantage of using for
loop over iterator?
任何人都可以回答這個問題嗎?
Can any body please answer this?
推薦答案
首先,有兩種for循環,它們的行為非常不同.一個使用索引:
First of all, there are 2 kinds of for loops, which behave very differently. One uses indices:
for (int i = 0; i < list.size(); i++) {
Thing t = list.get(i);
...
}
這種循環并不總是可能的.例如,List 有索引,但 Set 沒有,因為它們是無序的集合.
This kind of loop isn't always possible. For example, Lists have indices, but Sets don't, because they're unordered collections.
另一個,foreach 循環在幕后使用了一個迭代器:
The other one, the foreach loop uses an Iterator behind the scenes:
for (Thing thing : list) {
...
}
這適用于各種 Iterable 集合(或數組)
This works with every kind of Iterable collection (or array)
最后,您可以使用 Iterator,它也適用于任何 Iterable:
And finally, you can use an Iterator, which also works with any Iterable:
for (Iterator<Thing> it = list.iterator(); it.hasNext(); ) {
Thing t = it.next();
...
}
所以你實際上有 3 個循環要比較.
So you in fact have 3 loops to compare.
您可以用不同的術語來比較它們:性能、可讀性、易錯性、能力.
You can compare them in different terms: performance, readability, error-proneness, capability.
迭代器可以做一些 foreach 循環不能做的事情.例如,如果迭代器支持,您可以在迭代時刪除元素:
An Iterator can do things that a foreach loop can't. For example, you can remove elements while you're iterating, if the iterator supports it:
for (Iterator<Thing> it = list.iterator(); it.hasNext(); ) {
Thing t = it.next();
if (shouldBeDeleted(thing) {
it.remove();
}
}
列表還提供了可以雙向迭代的迭代器.foreach 循環只從頭到尾迭代.
Lists also offer iterators that can iterate in both directions. A foreach loop only iterates from the beginning to an end.
但迭代器更危險且可讀性更差.當你只需要一個 foreach 循環時,它是最易讀的解決方案.使用迭代器,您可以執行以下操作,這將是一個錯誤:
But an Iterator is more dangerous and less readable. When a foreach loop is all you need, it's the most readable solution. With an iterator, you could do the following, which would be a bug:
for (Iterator<Thing> it = list.iterator(); it.hasNext(); ) {
System.out.println(it.next().getFoo());
System.out.println(it.next().getBar());
}
foreach 循環不允許發生此類錯誤.
A foreach loop doesn't allow for such a bug to happen.
對于由數組支持的集合,使用索引訪問元素的效率稍高一些.但是如果你改變主意并使用 LinkedList 而不是 ArrayList,性能會突然變得很糟糕,因為每次訪問 list.get(i)
時,鏈表都必須循環所有它的元素直到第 i 個.迭代器(以及因此的 foreach 循環)沒有這個問題.它總是使用最好的方法來遍歷給定集合的元素,因為集合本身有它自己的 Iterator 實現.
Using indices to access elements is slightly more efficient with collections backed by an array. But if you change your mind and use a LinkedList instead of an ArrayList, suddenly the performance will be awful, because each time you access list.get(i)
, the linked list will have to loop though all its elements until the ith one. An Iterator (and thus the foreach loop) doesn't have this problem. It always uses the best possible way to iterate through elements of the given collection, because the collection itself has its own Iterator implementation.
我的一般經驗法則是:使用 foreach 循環,除非您真的需要迭代器的功能.當我需要訪問循環內的索引時,我只會使用帶有數組索引的 for 循環.
My general rule of thumb is: use the foreach loop, unless you really need capabilities of an Iterator. I would only use for loop with indices with arrays, when I need access to the index inside the loop.
這篇關于迭代器與 for的文章就介紹到這了,希望我們推薦的答案對大家有所幫助,也希望大家多多支持html5模板網!