简体   繁体   English

性能差异 For-Loop Foreach

[英]Performance Difference For-Loop Foreach

I always asked myself "what to use" should I use a for-loop or a foreach.我总是问自己“该使用什么”,我应该使用 for 循环还是 foreach。 In my opinion it's both the "same".在我看来,两者都是“相同的”。 I know for iterating through a list etc. is a foreach better but what if we have the following case :我知道遍历列表等是一个更好的 foreach 但如果我们有以下情况怎么办:

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

or或者

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

What would be better?什么会更好? Or is in this case really no difference?或者在这种情况下真的没有区别?

It is less about optimisation nowadays, as any difference will be unnoticeable, unless you need to process a very large amount of data. 如今,它与优化无关紧要,因为除非需要处理大量数据,否则任何差异都是不明显的。 Also, if you used a Collection, the performance would depend on the chosen implementation. 另外,如果您使用Collection,则性能将取决于所选的实现。

What you should really think about is the quality of the code. 您应该真正考虑的是代码的质量。 The rule is that you should use as few elements as possible to present the logic as clearly as possible . 规则是,应使用尽可能少的元素来尽可能清楚地呈现逻辑 The second solution introduces a new element, the i index, which is not actually needed and only makes the code this little bit more complicated. 第二种解决方案引入了一个新元素,即i索引,它实际上并不需要,只会使代码稍微复杂一点。 Only use the fori loop if you actually need to know the index in each iteration. 仅在确实需要在每次迭代中了解索引的情况下,才使用fori循环。

So, from code quality perspective, you should use the first solution :-) 因此,从代码质量的角度来看,您应该使用第一个解决方案:-)

If zipCodes[i] is not O(1), then the performance of your second case will be much worse. 如果zipCodes[i]不是O(1),那么第二种情况的性能将大大降低。 (That said, I don't think there yet exists a container in Java where [] is not O(1)). (这么说,我不认为有存在尚未在Java中的容器,其中[]不是 O(1))。 Put another way, the short form for loop cannot be slower. 换句话说,短期形式for循环不能慢。

Plus the short form for loop is clearer, which really ought to be the primary consideration unless speed matters . 加上短形式for循环更清晰,这确实应该是首要考虑的问题,除非速度的问题

First things first - for-each is nothing but syntactic sugar for Iterator .首先, for-each只不过是Iterator语法糖。 Read this section of JLS.阅读 JLS 的这一部分 So, I will address this question as a simple FOR loop vs Iterator.所以,我将这个问题作为一个简单的 FOR 循环 vs Iterator 来解决。

Now, when you use Iterator to traverse over a collection, at bare minimum you will be using two method - next() and hasNext() , and below are their ArrayList implementations:现在,当您使用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
    }

Now, we all know the basic computing that there will be performance difference if on the processor I have to just execute myArray[i] v/s complete implementation of next() method.现在,我们都知道基本计算,如果在处理器上我只需要执行myArray[i]next()方法的完整实现,就会有性能差异。 So, there has to be a difference in performance.因此,必须在性能上有所不同。

It is likely that some folk might come back strongly on this, citing performance benchmarks and excerpts from Effective Java, but the only other way I can try to explain is that this is even written in Oracle's official documentation - please read below from RandomAccess interface docs over here .很可能有些人可能会强烈反对这一点,引用了 Effective Java 的性能基准和摘录,但我可以尝试解释的唯一另一种方式是,这甚至写在 Oracle 的官方文档中 - 请阅读下面的RandomAccess接口文档这边

在此处输入图片说明

It is very clearly mentioned that there will be differences.很清楚的提到会有差异。 So, if you can convince me that what is written in official docs is wrong and will be changed, I will be ready to accept the argument that there is no performance difference between simple FOR loop and Iterator or for-each.所以,如果你能让我相信官方文档中写的东西是错误的并且会被更改,我将准备接受简单 FOR 循环和 Iterator 或 for-each 之间没有性能差异的论点。

So IMHO, correct way to put this whole argument is this:所以恕我直言,提出整个论点的正确方法是:

  1. If the collection implements RandomAccess interface then simple FOR loop will perform (at least theoretically) better than Iterator or for-each.如果集合实现了RandomAccess接口,那么简单的 FOR 循环将比 Iterator 或 for-each 执行(至少在理论上)更好。 (this is what is also written in RandomAccess docs ) (这也是RandomAccess docs 中所写的内容)
  2. If the collection doesn't implement RandomAccess interface then Iterator or for-each will perform (for sure) better than simple FOR loop.如果集合没有实现RandomAccess接口,那么 Iterator 或 for-each 将比简单的 FOR 循环执行(肯定)更好。
  3. However, for all practical purposes, for-each is the best choice in general.但是,出于所有实际目的,for-each 通常是最佳选择。

Note that there is no performance penalty for using the for-each loop, even for arrays. 请注意,即使对于数组,使用for-each循环也不会降低性能。 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. 实际上,在某些情况下,它可能只比普通的for循环提供一点性能优势,因为它只计算一次数组索引的限制。

Item 46 in Effective Java by Joshua Bloch Joshua Bloch撰写的有效Java项目46

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

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