迭代器与 for
我在一次采访中被问到使用迭代器比 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.
相关文章