-2

为什么枚举比 Iterator 更快?尽管迭代器比枚举具有更多优势。

4

1 回答 1

1

值得注意的是,枚举仅适用于较旧的线程安全集合。使用 Iterator 可以在任何集合上使用,并且由于它不必是线程安全的,因此没有额外的锁定开销。

public static void main(String... args) {
    Vector<Integer> vec = new Vector<>();
    ArrayList<Integer> al = new ArrayList<>();
    polulate(vec);
    polulate(al);
    for (int i = 0; i < 5; i++) {
        long start = System.nanoTime();
        long sum1 = enumSumOf(vec);
        long mid1 = System.nanoTime();
        long sum1b = iterSumOf(vec);
        long mid2 = System.nanoTime();
        long sum2 = iterSumOf(al);
        long end = System.nanoTime();
        System.out.printf("Each iteration of Enumeration took %,d ns (Vector), Iteration took %,d ns (Vector), Iteration took %,d ns (ArrayList)%n",
                (mid1 - start) / vec.size(), (mid2 - mid1) / vec.size(), (end - mid2) / al.size());
    }
}

private static long enumSumOf(Vector<Integer> vec) {
    long sum = 0;
    for (Enumeration<Integer> e = vec.elements(); e.hasMoreElements(); )
        sum += e.nextElement();
    return sum;
}

private static long iterSumOf(Vector<Integer> al) {
    long sum = 0;
    for (int i : al)
        sum += i;
    return sum;
}

private static long iterSumOf(ArrayList<Integer> al) {
    long sum = 0;
    for (int i : al)
        sum += i;
    return sum;
}

private static void polulate(List<Integer> l) {
    for (int i = 0; i < 1000000; i++)
        l.add(i);
}

印刷

Each iteration of Enumeration took 61 ns (Vector), 
    Iteration took 74 ns (Vector), Iteration took 17 ns (ArrayList)
Each iteration of Enumeration took 52 ns (Vector), 
    Iteration took 54 ns (Vector), Iteration took 6 ns (ArrayList)
Each iteration of Enumeration took 52 ns (Vector),  
    Iteration took 54 ns (Vector), Iteration took 6 ns (ArrayList)
Each iteration of Enumeration took 52 ns (Vector),  
    Iteration took 53 ns (Vector), Iteration took 6 ns (ArrayList)
Each iteration of Enumeration took 40 ns (Vector),  
    Iteration took 36 ns (Vector), Iteration took 5 ns (ArrayList)

在给出的微基准示例中,Enumeration 比 Iterator 快的原因是因为它首先经过测试。;)

更长的答案是,当循环迭代 10,000 次时,HotSpot 编译器会优化整个方法。-XX:CompileThreshold=NNNN 当你有两个循环时,你可以用你可以看到的相同方法来改变它。

  • 第一个测试较慢,因为它在运行的某些时候没有优化,而第二个循环在开始之前进行了优化。
  • 第二个测试速度较慢,因为 JVM 在运行时收集优化指标并使用这些指标来优化代码。如果在收集任何指标之前优化代码,它可能会慢得多。

显示这种情况的一种简单方法是交换循环的顺序。更好的解决方案是将每个循环放在自己的方法中并重复测试几次。这确保了它们被独立优化并且结果是可重复的。

于 2012-06-14T08:14:09.340 回答