Java 为什么 Android Studio 要我使用 For Each 而不是 For Loop?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/32548820/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-11 12:44:38  来源:igfitidea点击:

Why does Android Studio want me to use For Each instead of For Loop?

javafor-loopandroid-studioforeach

提问by user1714647

This question has been struggling me for time. Why sometimes does Android Studio want me to use For Each instead of For Loop, because when I use For Loop, I get a warning that I could be using for each (and with Alt+Enter it suggests me the autofix).

这个问题一直困扰着我。为什么有时 Android Studio 想让我使用 For Each 而不是 For Loop,因为当我使用 For Loop 时,我收到一个警告,我可以使用 for each(并且使用 Alt+Enter 会提示我自动修复)。

For example let's suppose we have this code

例如让我们假设我们有这个代码

String a = "";
String[] array = {"A","B","C"};

for(int i = 0; i < array.length; i++) {
    a += array[i];
    a += ",";
}

I get a warning

我收到警告

and this is the fix suggested by Android Studio

这是 Android Studio 建议的修复

for (String anArray : array) {
        a += anArray;
        a += ",";
}

Is it more performant? There's a reason I should get a warningfor actually using just for loop?

它的性能更高吗?有一个原因我应该因为实际仅使用 for 循环而收到警告

Or when it's better for loop or for each?

或者什么时候循环或每个更好?

采纳答案by Riddhesh Sanghvi

From the book: Effective Java (2nd Edition) by Joshua Bloch

来自这本书:Joshua Bloch 的 Effective Java(第 2 版)

The for-each loop, introduced in release 1.5, gets rid of the clutter and the opportunity for error by hiding the iterator or index variable completely. The resulting idiom applies equally to collections and arrays:

1.5 版中引入的 for-each 循环通过完全隐藏迭代器或索引变量来消除混乱和出错的机会。由此产生的习语同样适用于集合和数组:

    // The preferred idiom for iterating over collections and arrays
     for (Element e : elements) {
         doSomething(e);
     }

When you see the colon (:), read it as “in.” Thus, the loop above reads as “for each element e in elements.” 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. While you can do this by hand (Item 45), programmers don't always do so.

当您看到冒号 (:) 时,将其读为“in”。因此,上面的循环读作“对于元素中的每个元素 e”。请注意,使用 for-each 循环没有性能损失,即使是数组也是如此。事实上,在某些情况下,它可能比普通的 for 循环提供轻微的性能优势,因为它只计算一次数组索引的限制。虽然您可以手动执行此操作(第 45 条),但程序员并不总是这样做。


Here is a comparison from http://developer.android.com/training/articles/perf-tips.html#Loops:


这是来自http://developer.android.com/training/articles/perf-tips.html#Loops的比较:

static class Foo {
    int mSplat;
}

Foo[] mArray = ...

public void zero() {
    int sum = 0;
    for (int i = 0; i < mArray.length; ++i) {
        sum += mArray[i].mSplat;
    }
}

public void one() {
    int sum = 0;
    Foo[] localArray = mArray;
    int len = localArray.length;

    for (int i = 0; i < len; ++i) {
        sum += localArray[i].mSplat;
    }
}

public void two() {
    int sum = 0;
    for (Foo a : mArray) {
        sum += a.mSplat;
    }
}

zero()is slowest, because the JIT can't yet optimize away the cost of getting the array length once for every iteration through the loop.

one()is faster. It pulls everything out into local variables, avoiding the lookups. Only the array length offers a performance benefit.

two()is fastest for devices without a JIT, and indistinguishable from one()for devices with a JIT. It uses the enhanced for loop syntax introduced in version 1.5 of the Java programming language.

So, you should use the enhanced for loop by default, but consider a hand-written counted loop for performance-critical ArrayList iteration.

zero()是最慢的,因为 JIT 还不能优化循环每次迭代获取数组长度的成本。

one()是比较快的。它将所有内容提取到局部变量中,避免查找。只有数组长度提供了性能优势。

two()对于没有 JIT 的设备来说是最快的,并且与带有 JIT 的设备没有区别 one()。它使用 Java 编程语言 1.5 版中引入的增强的 for 循环语法。

因此,您应该默认使用增强的 for 循环,但考虑使用手写计数循环进行性能关键的 ArrayList 迭代。

回答by Dici

It's just more readable when you just iterate without looking ahead or backward. Well, it's readable if you choose a good variable name (unlike anArrayfor a String:D). It's a bit safer too because if you were a really stupid programmer you could write array[2 * i]and throw an ArrayOutOfBoundsException. Apart from this, I find it a bit exaggerated to ask you to refactor that... this is a common idiom in Java.

当您只是迭代而不向前或向后看时,它的可读性更高。好吧,如果你选择一个好的变量名(不像它的可读性anArrayString:d)。这也更安全一些,因为如果你是一个非常愚蠢的程序员,你可以编写array[2 * i]并抛出一个ArrayOutOfBoundsException. 除此之外,我觉得要求你重构它有点夸张......这是Java中的一个常见习语。