Java For-each 与迭代器。哪个是更好的选择
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/18508786/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
For-each vs Iterator. Which will be the better option
提问by Ruchira Gayan Ranaweera
Consider the following scenario.
考虑以下场景。
List<String> list = new ArrayList<>();
Now I added the String
values for this list.
现在我String
为这个列表添加了值。
I used following ways to go each and every element in the list.
我使用以下方法处理列表中的每个元素。
Option one- use for-each
选项一——使用 for-each
for (String i : list) {
System.out.println(i);
}
Option two- use Iterator
选项二 - 使用 Iterator
Iterator it=list.iterator();
while (it.hasNext()){
System.out.println(it.next());
}
I just want to know is there any performance advantage if I use for-each
instead of Iterator
. And also is it a bad practice to use Iterator now a days in Java?
我只想知道如果我使用for-each
而不是Iterator
. 而且现在在 Java 中使用 Iterator 是一种不好的做法吗?
采纳答案by Tala
for-each
is syntactic sugar for using iterators
(approach 2).
for-each
是 using 的语法糖iterators
(方法 2)。
You might need to use iterators
if you need to modify collection in your loop. First approach will throw exception.
iterators
如果您需要修改循环中的集合,则可能需要使用。第一种方法会抛出异常。
for (String i : list) {
System.out.println(i);
list.remove(i); // throws exception
}
Iterator it=list.iterator();
while (it.hasNext()){
System.out.println(it.next());
it.remove(); // valid here
}
回答by Uwe Plonus
Simple answers: No and no.
简单的答案:不,不。
Internally the for-each
loop creates an Iterator
to iterate through the collection.
在内部,for-each
循环创建一个Iterator
以遍历集合。
The advantage of using the Iterator
explicitly is that you can access the Iterator
s method.
Iterator
显式使用 的优点是您可以访问Iterator
s 方法。
回答by Aniket Thakur
for-each
is an advanced looping construct. Internally it creates an Iterator and iterates over the Collection. Only possible advantage of using an actual Iterator object over the for-each
construct is that you can modify your collection using Iterator's methods like .remove()
. Modifying the collection without using Iterator's methods while iterating will produce a ConcurrentModificationException.
for-each
是一种高级循环结构。它在内部创建一个迭代器并迭代集合。使用实际的 Iterator 对象而不是for-each
构造的唯一可能优势是您可以使用 Iterator 的方法(如.remove()
. 在迭代时不使用 Iterator 的方法修改集合将产生ConcurrentModificationException。
回答by Ashish Chaurasia
The difference is largely syntactic sugar except that an Iterator can remove items from the Collection it is iterating. Technically, enhanced for loops allow you to loop over anything that's Iterable, which at a minimum includes both Collections and arrays.
区别主要在于语法糖,除了 Iterator 可以从它正在迭代的 Collection 中删除项目。从技术上讲,增强的 for 循环允许您遍历任何可迭代的东西,其中至少包括集合和数组。
Don't worry about performance differences. Such micro-optimization is an irrelevant distraction. If you need to remove items as you go, use an Iterator. Otherwise for loops tend to be used more just because they're more readable ie:
不要担心性能差异。这种微优化是无关紧要的干扰。如果您需要随时删除项目,请使用迭代器。否则 for 循环往往会被更多地使用,因为它们更具可读性,即:
for (String s : stringList) { ... }
vs:
对比:
for (Iterator<String> iter = stringList.iterator(); iter.hasNext(); ) {
String s = iter.next();
...
}
回答by Bob
If you want to replace items in your List, I would go old school with a for loop
如果你想替换你列表中的项目,我会用 for 循环去老派
for (int nIndex=0; nIndex < list.size(); nIndex++) {
Obj obj = (Obj) list.get(nIndex);
// update list item
list.set(nIndex, obj2);
}
回答by Maleen Abewardana
Best way to do this is in java 8 is,
最好的方法是在 java 8 中,
list.forEach(System.out::println);
Here are some useful links.
这里有一些有用的链接。
回答by Birchlabs
foreach
uses iterators under the hood anyway. It really is just syntactic sugar.
foreach
无论如何都在幕后使用迭代器。它真的只是语法糖。
Consider the following program:
考虑以下程序:
import java.util.List;
import java.util.ArrayList;
public class Whatever {
private final List<Integer> list = new ArrayList<>();
public void main() {
for(Integer i : list) {
}
}
}
Let's compile it with javac Whatever.java
,
And read the disassembled bytecode of main()
, using javap -c Whatever
:
让我们编译它javac Whatever.java
,
而读取的字节码拆卸main()
,使用javap -c Whatever
:
public void main();
Code:
0: aload_0
1: getfield #4 // Field list:Ljava/util/List;
4: invokeinterface #5, 1 // InterfaceMethod java/util/List.iterator:()Ljava/util/Iterator;
9: astore_1
10: aload_1
11: invokeinterface #6, 1 // InterfaceMethod java/util/Iterator.hasNext:()Z
16: ifeq 32
19: aload_1
20: invokeinterface #7, 1 // InterfaceMethod java/util/Iterator.next:()Ljava/lang/Object;
25: checkcast #8 // class java/lang/Integer
28: astore_2
29: goto 10
32: return
We can see that foreach
compiles down to a program which:
我们可以看到foreach
编译成一个程序:
- Creates iterator using
List.iterator()
- If
Iterator.hasNext()
: invokesIterator.next()
and continues loop
- 使用创建迭代器
List.iterator()
- 如果
Iterator.hasNext()
:调用Iterator.next()
并继续循环
As for "why doesn't this useless loop get optimized out of the compiled code? we can see that it doesn't do anything with the list item": well, it's possible for you to code your iterable such that .iterator()
has side-effects, or so that .hasNext()
has side-effects or meaningful consequences.
至于“为什么这个无用的循环没有从编译后的代码中得到优化?我们可以看到它对列表项没有做任何事情”:好吧,您可以编写.iterator()
具有副作用的可迭代对象,或因此.hasNext()
产生副作用或有意义的后果。
You could easily imagine that an iterable representing a scrollable query from a database might do something dramatic on .hasNext()
(like contacting the database, or closing a cursor because you've reached the end of the result set).
您可以很容易地想象,代表来自数据库的可滚动查询的迭代可能会做一些戏剧性的事情.hasNext()
(比如联系数据库,或者因为您已经到达结果集的末尾而关闭游标)。
So, even though we can prove that nothing happens in the loop body… it is more expensive (intractable?) to prove that nothing meaningful/consequential happens when we iterate. The compiler has to leave this empty loop body in the program.
因此,即使我们可以证明循环体中没有发生任何事情……证明在我们迭代时没有发生任何有意义的/后果性的事情成本更高(难以处理?)。编译器必须在程序中留下这个空的循环体。
The best we could hope for would be a compiler warning. It's interesting that javac -Xlint:all Whatever.java
does notwarn us about this empty loop body. IntelliJ IDEA does though. Admittedly I have configured IntelliJ to use Eclipse Compiler, but that may not be the reason why.
我们所能希望的最好结果是编译器警告。有趣的是,javac -Xlint:all Whatever.java
它不会警告我们这个空循环体。IntelliJ IDEA 确实如此。诚然,我已将 IntelliJ 配置为使用 Eclipse 编译器,但这可能不是原因。
回答by Rahul Raina
Here is simple code snippet to check the performance of For-each
vs Iterator
vs for
for the traversal of ArrayList<String>
, performed on Java version 8.
这是一个简单的代码片段,用于检查For-each
vs Iterator
vsfor
遍历 的性能ArrayList<String>
,在 Java 版本 8 上执行。
long MAX = 2000000;
ArrayList<String> list = new ArrayList<>();
for (long i = 0; i < MAX; i++) {
list.add("" + i);
}
/**
* Checking with for each iteration.
*/
long A = System.currentTimeMillis();
for (String data : list) {
// System.out.println(data);
}
long B = System.currentTimeMillis();
System.out.println(B - A + "ms");
/**
* Checking with Iterator method
*/
Iterator<String> iterator = list.iterator();
while (iterator.hasNext()) {
iterator.next();
// System.out.println(iterator.next());
}
long C = System.currentTimeMillis();
System.out.println(C - B + "ms");
/**
* Checking with normal iteration.
*/
for (int i = 0; i < MAX; i++) {
list.get((int) (i % (MAX - i)));
// System.out.println(list.get(i));
}
long D = System.currentTimeMillis();
System.out.println(D - C + "ms");
Average Output values:
平均输出值:
19ms
9ms
27ms
Result Analysis:
Iterator
(9ms) <For-each
(19ms) <For
(27ms)Here
Iterator
has the best performanceandFor
has the least performance. HoweverFor-each
performance lies somewhere in between.
结果分析:
Iterator
(9ms) <For-each
(19ms) <For
(27ms)这里
Iterator
有最好的性能,并For
具有至少一个演出。然而,For-each
性能介于两者之间。