有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

循环Foreach的java性能差异

我总是问自己“使用什么”应该使用for循环还是foreach。 在我看来,两者都是“相同的”。我知道通过列表等进行迭代是一种更好的方法,但如果我们有以下情况会怎么样:

for (String zipCode : zipCodes) {
    if (zipCode.equals(zip)) {
        return true;
    }
}

for (int i = 0; i < zipCodes.length; i++) {
    if (zipCodes[i].equals(zip)) {
        return true;
    }
}

什么会更好?还是在这种情况下真的没有区别


共 (4) 个答案

  1. # 1 楼答案

    如今,这与优化无关,因为任何差异都不会被注意到,除非你需要处理大量数据。此外,如果使用集合,性能将取决于所选的实现

    你真正应该考虑的是代码的质量。规则是,你应该使用尽可能少的元素来尽可能清晰地呈现逻辑。第二个解决方案引入了一个新元素i index,它实际上并不需要,只会让代码变得更复杂一点。只有在每次迭代中确实需要知道索引时才使用fori循环

    因此,从代码质量的角度来看,您应该使用第一种解决方案:-)

  2. # 2 楼答案

    Note that there is no performance penalty for using the for-each loop, even for arrays. In fact, it may offer a slight performance advantage over an ordinary for loop in some circumstances, as it computes the limit of the array index only once.

    约书亚·布洛赫的《有效Java》第46条

  3. # 3 楼答案

    如果zipCodes[i]不是O(1),那么第二个案例的性能会差得多。(也就是说,我不认为Java中存在但是存在一个容器,其中[]而不是O(1))。换句话说,短形式的forloop不能再慢了

    此外,简短形式的for循环更清晰,这确实应该是首要考虑因素,除非速度影响

  4. # 4 楼答案

    第一件事第一-for-each只不过是Iterator的语法糖。阅读JLS的this section。所以,我将以一个简单的FOR循环vs迭代器来解决这个问题

    现在,当您使用Iterator遍历一个集合时,至少要使用两种方法next()hasNext(),下面是它们的ArrayList实现:

        public boolean hasNext() {
            return cursor != size;
        }
    
        @SuppressWarnings("unchecked")
        public E next() {
            checkForComodification();
            int i = cursor;
            if (i >= size)
                throw new NoSuchElementException();
            Object[] elementData = ArrayList.this.elementData;
            if (i >= elementData.length)
                throw new ConcurrentModificationException();
            cursor = i + 1;
            return (E) elementData[lastRet = I]; // hagrawal: this is what simple FOR loop does
        }
    

    现在,我们都知道,如果在处理器上执行myArray[i]v/s next()方法的完整实现,将会有性能上的差异。因此,在性能上必须有所不同

    很可能有些人会强烈反对这一点,引用性能基准和有效Java的摘录,但我能尝试解释的唯一其他方式是,这甚至是在Oracle的官方文档中写的——请阅读下面的RandomAccess接口文档

    enter image description here

    这是非常明确地提到,将有分歧。所以,如果你能让我相信官方文档中写的内容是错误的,并且会被更改,我将准备接受这样的观点,即简单FOR循环和迭代器FOR each之间没有性能差异

    所以,我认为,正确的说法是:

    1. 如果集合实现了RandomAccess接口,那么简单FOR循环的性能(至少在理论上)将优于迭代器FOR each。(这也是用RandomAccess docs写的)
    2. 如果集合没有实现RandomAccess接口,那么迭代器or for each的性能(肯定)会比simple for循环好
    3. 然而,就所有实际目的而言,一般来说,每种方法都是最好的选择