web-dev-qa-db-ja.com

Android StudioでFor Loopの代わりにFor Eachを使用する必要があるのはなぜですか?

この質問は私にとって長い間苦労してきました。 Android StudioがFor Loopの代わりにFor Eachを使用することを望んでいる理由は、For Loopを使用すると、For Eachを使用している可能性があるという警告が表示されるためです(Alt + Enterを使用) autofixを提案します)。

たとえば、次のコードがあるとします

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

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

警告が出ます

これはAndroid Studioによって提案された修正です

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

よりパフォーマンスが高いですか?実際にちょうどforループを使用するためにwarningを取得する必要がある理由はありますか?

または、forループまたはeachのどちらが優れているか?

10
user1714647

本から:Joshua BlochによるEffective Java(2nd Edition))

リリース1.5で導入されたfor-eachループは、イテレータまたはインデックス変数を完全に非表示にすることで、煩雑さとエラーの可能性を取り除きます。結果のイディオムは、コレクションと配列に等しく適用されます。

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

コロン(:)が表示されたら、「中」と読みます。したがって、上記のループは「要素内の各要素eとして」と読み取ります。配列の場合でも、for-eachループを使用してもパフォーマンスが低下しないことに注意してください。実際、配列のインデックスの制限は1回しか計算されないため、状況によっては、通常のforループよりもわずかにパフォーマンスが向上する場合があります。これは手動で行うことができますが(項目45)、プログラマーは常にそうするわけではありません。


これは 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()が最も遅いのは、JITがまだループ全体の反復ごとに1回配列長を取得するコストを最適化できないためです。

one()の方が高速です。ルックアップを回避して、すべてをローカル変数に引き出します。パフォーマンスが向上するのは、アレイの長さだけです。

two()はJITのないデバイスの場合は最速で、JITのあるデバイスの場合はone()と区別できません。 Javaプログラミング言語のバージョン1.5で導入された拡張forループ構文を使用します。

したがって、デフォルトでは拡張forループを使用する必要がありますが、パフォーマンスが重要なArrayListの反復には手書きのカウントループを検討してください。

28

前方または後方を向かずに反復するだけで読みやすくなります。まあ、(anArray:DのStringとは異なり)適切な変数名を選択すればそれは読みやすくなります。あなたが本当に愚かなプログラマーならarray[2 * i]と書いてArrayOutOfBoundsExceptionを投げることができるので、それも少し安全です。これとは別に、私はあなたにそれをリファクタリングするように頼むことは少し誇張されていると思います...これはJavaの一般的な慣用句です。

1
Dici