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

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-12 08:39:53  来源:igfitidea点击:

For-each vs Iterator. Which will be the better option

javaforeachiterator

提问by Ruchira Gayan Ranaweera

Consider the following scenario.

考虑以下场景。

List<String> list = new ArrayList<>();

Now I added the Stringvalues 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-eachinstead 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-eachis syntactic sugar for using iterators(approach 2).

for-each是 using 的语法糖iterators(方法 2)。

You might need to use iteratorsif 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-eachloop creates an Iteratorto iterate through the collection.

在内部,for-each循环创建一个Iterator以遍历集合。

The advantage of using the Iteratorexplicitly is that you can access the Iterators method.

Iterator显式使用 的优点是您可以访问Iterators 方法。

回答by Aniket Thakur

for-eachis 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-eachconstruct 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 Birchlabs

foreachuses 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 foreachcompiles down to a program which:

我们可以看到foreach编译成一个程序:

  • Creates iterator using List.iterator()
  • If Iterator.hasNext(): invokes Iterator.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.javadoes 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 编译器,但这可能不是原因。

enter image description here

在此处输入图片说明

回答by Rahul Raina

Here is simple code snippet to check the performance of For-eachvs Iteratorvs forfor the traversal of ArrayList<String>, performed on Java version 8.

这是一个简单的代码片段,用于检查For-eachvs Iteratorvsfor遍历 的性能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 Iteratorhas the best performanceand Forhas the least performance. However For-eachperformance lies somewhere in between.

结果分析:Iterator(9ms) < For-each(19ms) < For(27ms)

这里Iterator有最好的性能,并For具有至少一个演出。然而,For-each性能介于两者之间。