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

时间:2014-10-19 20:24:29

标签: java loops collections

在浏览特定 集合 的元素时,我总是对每个 循环使用

只是为了检查每个循环过程消耗多少时间,我这样编码,

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();

    }

}

令人惊讶的是,通过 为每个 循环完成的循环过程仅落后于简单的 for loop 。(在具有不同配置的不同机器上,结果可能会有所不同。)

控制台输出:

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

那么为什么人们更喜欢通过每个 循环的 来实现呢?基于性能有什么理由吗?

4 个答案:

答案 0 :(得分:1)

IIRC,for-each循环只是一个语法糖,当通过集合进行迭代时,它将被编译为for循环与迭代器。在运行时,应该没有性能差异。

您看到的差异是一个写得不好的基准逻辑的典型结果。如果你把'#34; for循环用iterator&#34;作为第一个调用的方法,你会发现它运行缓慢。

更不用说每次测试的持续时间太短而不显着,在我添加了一些热身之后(首先运行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

forEachloop的结果,useForLoopWithIterator和useWhileLoop几乎完全相同(应该是它们)。通过集合迭代时基于索引的访问几乎是最不受欢迎的。虽然这里的差异并不显着,但如果您使用非基于数组的集合,则会看到更大的差异,例如:链表。

答案 1 :(得分:0)

我使用它是为了方便。您不需要考虑&#34; for(类型e:设置)​​的边界和条件。

答案 2 :(得分:0)

只要代码足够快,我就会追求简单/可维护性。只有当性能成为问题时,我才会考虑进行优化。即便如此,工作流程的某些部分可能会在优化时产生更大的性能提升。

答案 3 :(得分:0)

“有效Java”一书涵盖了这一点。基本上,foreach是简洁而优雅的,任何人都可以阅读和理解代码。总是说永远不要过早地进行优化。只有在您完全确定需要时才考虑优化。因此,如果您发现找到它是非常常见的,因为它更容易理解,维护和优化已确定当时不需要。