8

インデックスが必要なときに配列をループする最良の方法は何ですか?

オプション1:

int len = array.length;
for (int i = 0; i < len; ++i) {
    array[i] = foo(i);
}

オプション2:

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

または、それは問題ではありませんか?それともそれを行うためのより良い方法はありますか?違いを指摘するだけです。ある場合、配列の長さはループ内のテストの一部として評価されますが、コンパイラーは通常それを最適化する必要があります。


第二に、++iここと何か違いはありi++ますか?++i私はそれがC++であるかどうかは間違いなく好きですが、Javaについてはよくわかりません。

4

4 に答える 4

6

i++この特定のケースでは、 vs++iは重要ではありません。Cマスターは、array.lengthを変数に格納するように指示しますが、最新の最適化コンパイラーは、ループ内で長さが変更されない限り、この場合は不要にします。本当に心配している場合は、両方のベンチマークを実行できますが、.length実際には毎回配列全体をトラバースする必要がないため、問題はありません。

于 2012-09-29T02:43:44.907 に答える
6

通常、これら2つの方法は同等です。あなたはで注意する必要があります

for (int i = 0 ; i < foo() ; i++) {
    ...
}

これfoo()は(最初の反復の前に1回だけではなく)各反復の前に1回呼び出されるため、次のようなことを行うことで、より複雑な状況でこれを考慮に入れることができます。

int n = foo();
for (int i = 0 ; i < n ; i++) {
    ...
}

これは、オプション1に類似しています。したがって、オプション1は確かに2つのうち安全であると言えますが、ほとんどの場合、使用するものに大きな違いはありません。


2番目の質問については、++i最初に変数をインクリメントしてからi++その値を取得し、最初に値を取得してからインクリメントします。次の2つのコードを試してみてください。

int i = 0;
System.out.println(++i);
------------------------
int i = 0;
System.out.println(i++);

最初は印刷されます1が、2番目は印刷され0ます。もちろん、一人でいるとき++ii++違いはありません。

于 2012-09-29T02:45:28.067 に答える
0

forループで「array.length」を使用するかどうかについて:通常、コンパイラーはある程度の最適化を行います。その結果、forループで変数を使用するのと同じです。

「i++」および「++i」の場合C++では、++ iが優先され、より効率的ですが、Javaでは、この場合は同等です。

于 2012-09-29T03:12:29.787 に答える
0

size()arshajiの応答に加えて、ループで使用することと事前に保存することのパフォーマンス上の利点があるかどうかを知りたいと思いました。結果は、コンパイラが物事を最適化し、リストの長さにアクセスすることは変数にアクセスすることと同じであることを示していると思います(関数を経由する必要があるという事実が物事を遅くするのではないかと心配していました)。

ループの異なる方法でこれら2つにかかる時間は次のとおりです。

for(long i = 0 ; i < mylist.size(); i++){}
VS
for(long i = 0 ; i < 10_000_000; i++){}

1000万の要素のリストの結果は次のとおりです。

fixed length:
,162,157,151,157,156,159,157,149,150,170,158,153,152,158,151,151,156,156,151,153
getSize:
,164,156,159,154,151,160,162,152,154,152,151,149,168,156,152,150,157,150,156,157



import java.util.ArrayList;
import java.util.List;

public class Main {

    final static int LENGTH_SAMPLE = 20;
    final static long LENGTH = 10_000_000;

    public static void main(String[] args) {

        List<Long> mylist = new ArrayList<>();
        for(long i = 0 ; i < LENGTH; i++){
            mylist.add(i);
        }
        System.out.println("fixed length:");
        for(int i = 0 ; i < LENGTH_SAMPLE; i++){
            System.out.printf("," + fixedSize(mylist));
        }
        System.out.println("");
        System.out.println("getSize:");
        for(int i = 0 ; i < LENGTH_SAMPLE; i++){
            System.out.printf("," + fctSize(mylist));
        }
    }

    private static long fixedSize(List list){
        long start = System.currentTimeMillis();

        for(long i = 0 ; i < LENGTH; i++){
            System.currentTimeMillis();
        }
        return System.currentTimeMillis() - start;
    }

    private static long fctSize(List list){
        long start = System.currentTimeMillis();

        for(long i = 0 ; i < list.size(); i++){
            System.currentTimeMillis();
        }
        return System.currentTimeMillis() - start;
    }
}
于 2016-06-03T23:50:24.180 に答える