简体   繁体   English

哪一个是迭代特定集合元素的最佳方法?

[英]Which one is the best way to iterate the elements of a particular collection?

I always use for each loop while going through the elements of a particular collection . 我总是在浏览特定集合的元素时使用每个循环。

Just to check how much time each looping process consumes, i coded like this, 只是为了检查每个循环过程消耗多少时间,我这样编码,

public class LoopingDemo {
    static ArrayList<String> arrayList = new ArrayList<String>();
    static double start;
    static double end;

    public static void iterator() {
        simpleForLoop();
        System.out.println();
        forEachLoop();
        System.out.println();
        useWhileLoop(arrayList);
        System.out.println();
        useForLoop(arrayList);
        System.out.println();
        enumerator();
    }
    public static void simpleForLoop(){
        start = System.nanoTime();
        for(int i=0;i<arrayList.size();i++){
            String str = arrayList.get(i);
            System.out.println(": "+str);
        }
        end = System.nanoTime();
        System.out.println("Taken taken in simpleForLoop process: "
            + (end - start));
    }

    public static void forEachLoop() {
        start = System.nanoTime();
        for (String str : arrayList) {
        System.out.println(str);
    }
        end = System.nanoTime();
        System.out.println("Taken taken in forEachLoop process: "
            + (end - start));
    }

    public static void enumerator() {
        start = System.nanoTime();

        // get the Enumeration object
        Enumeration<String> en = Collections.enumeration(arrayList);

        // enumerate through the ArrayList elements
        System.out.println("Enumerating through Java ArrayList");

        while (en.hasMoreElements()) {
            System.out.println(en.nextElement());
            /*
             * String name = (String) en.nextElement();
             * System.out.println(name);
             */
        } 
        end = System.nanoTime();
        System.out.println("Taken taken in enumeration process: "
            + (end - start));
    }

    private static void useWhileLoop(Collection<String> myList) {
        start = System.nanoTime();
        Iterator<String> itr = myList.iterator();
        while (itr.hasNext()) {
            String str = itr.next(); // Returns the next element in the
                                    // iteration.
            System.out.println(str);
            // System.out.println(itr.next()); // in one line
        }
        end = System.nanoTime();
        System.out.println("Taken taken in useWhileLoop process: "
            + (end - start));
    }

    /**
     * Note that this for-loop does not use an integer index.
     */
    private static void useForLoop(Collection<String> myList) {
        start = System.nanoTime();
        for (Iterator<String> itr = myList.iterator(); itr.hasNext();) {
            System.out.println(itr.next());
        }
        end = System.nanoTime();
        System.out.println("Taken taken in useForLoopWithIterator process: "
            + (end - start));
    }

    public static void addElements() {

        // Add elements to the array list.
        arrayList.add("C");
        arrayList.add("A");
        arrayList.add("E");
        arrayList.add("B");
        arrayList.add("D");
        arrayList.add("F");
        arrayList.add(1, "A2");

    }

    public static void main(String[] args) {
        addElements();
        iterator();

    }

}

Surprisingly, the looping process done through for each loop only lags behind the simple for loop .(Results may vary on different machines with different configurations.) 令人惊讶的是, 为每个循环完成的循环过程仅落后于简单的for循环 。(结果可能因具有不同配置的不同机器而异。)

Console output: 控制台输出:

Taken taken in simpleForLoop process:              853200.0
Taken taken in forEachLoop process:                788993.0
Taken taken in useWhileLoop process:               452014.0
Taken taken in useForLoopWithIterator process:     299775.0
Taken taken in enumeration process:                766756.0

So why do the people prefer to do it through the for each loop? 那么为什么人们更喜欢通过每个循环来做呢? Is there any reason based on performance? 基于性能有什么理由吗?

IIRC, for-each loop is simply a syntax sugar that will be compiled to for loop with iterator when iterating thru a collection. IIRC,for-each循环只是一个语法糖,当通过集合迭代时,它将被编译为for循环与迭代器。 On runtime there should be no performance difference. 在运行时,应该没有性能差异。

The difference you see is a typical result of a poorly written benchmarking logic. 你看到的差异是一个写得不好的基准逻辑的典型结果。 If you put "for loop with iterator" as the first method to call, you will find it run slow. 如果你把“for loop with iterator”作为第一个调用方法,你会发现它运行缓慢。

Not to mention the duration for each test is too short to be significant, after I have added some warm up (run everything 5 times first, and look at the result of the 6th result), the result become normal: 更不用说每次测试的持续时间太短而不显着,在我添加了一些热身之后(首先运行5次,然后查看第6个结果的结果),结果变得正常:

Taken taken in useForLoopWithIterator process: 105110.0
Taken taken in simpleForLoop process: 122181.0
Taken taken in useWhileLoop process: 104774.0
Taken taken in enumeration process: 123520.0
Taken taken in forEachLoop process: 106782.0

The result of forEachloop, useForLoopWithIterator and useWhileLoop is almost identical (for which they should be). forEachloop的结果,useForLoopWithIterator和useWhileLoop几乎完全相同(应该是它们)。 Index-based access when iterating thru collection is almost least-preferred. 通过集合迭代时基于索引的访问几乎是最不受欢迎的。 Although the difference is not significant here, you will see a bigger difference if you are using non-array-based collection, eg LinkedList. 虽然这里的差异并不显着,但如果使用非基于数组的集合,例如LinkedList,则会看到更大的差异。

I use it for convenience. 我使用它是为了方便。 You don't need to consider the boundary and condition with "for (Type e : set). 您不需要使用“for(类型e:set)”来考虑边界和条件。

As long as code is fast enough, I would go for simplicity/maintainability. 只要代码足够快,我就会追求简单/可维护性。 Only if performance becomes an issue would I consider optimizing. 只有当性能成为问题时,我才会考虑进行优化。 And even then, there might be parts of the workflow that will yield much greater performance gains when optimizing. 即便如此,工作流程的某些部分可能会在优化时产生更大的性能提升。

The book Effective Java covers this. “有效Java”一书涵盖了这一点。 Basically, foreach is concise and elegant for anyone to read and understand the code. 基本上,foreach是简洁而优雅的,任何人都可以阅读和理解代码。 It's always said never to optimize prematurely. 总是说永远不要过早优化。 Only look at optimizing when you are absolutely certain it's needed. 只有在你完全确定需要时才考虑优化。 So if you find that it's very common to find foreach it's because it's been because it's easier to understand, maintain and optimizing has been determined not needed at that moment. 因此,如果您发现找到foreach是非常常见的,那是因为它更容易理解,维护和优化已确定当时不需要。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM