6

指定された座標が配列内にあるかどうかを確認したい。

public boolean checkBounds(int x, int y) {
    try {
        Object val = array[x][y];
        return true;
    } catch (ArrayIndexOutOfBoundsException e) {
        return false;
    }
}

私はそのようにすることができますか?それはそれを行う効率的な方法ですか?

4

1 に答える 1

13

例外を使用して境界チェックを実行するとどうなりますか?

null チェック、境界チェック、ファイル存在チェックなどの処理操作に例外を使用すると、例外がスローされるたびに多くのオーバーヘッドが発生します。

単純に境界をチェックした場合、次のようになります。

  • 配列のサイズを 0 と
  • 結果を返す

例外ベースのチェックを使用するときに実際に行っていること:

  • 配列の境界をチェックする
  • Java 例外メカニズムを開始します (すべてのオーバーヘッドを含む)
  • 新しい例外オブジェクトを作成する
  • スタック トレース全体をダンプする
  • 新しく作成されたオブジェクトをすべてのスタック データで埋める
  • 例外をキャッチ
  • 結果を返す

性能比較

この簡単なテスト プログラムを使用して、両方のタイプの配列境界チェックの速度を測定しました。

public class BoundsCheckTest {

    final static int[] array = new int[1];
    final static Random gen = new Random();

    public static void main(String[] args){

        boolean ret = false;
        int tries = 100000000;
        long timestart = System.nanoTime();

        for (int a=0; a< tries; a++) {
            ret = method1();
        }
        long timeend1 = System.nanoTime();
        System.out.println();

        for (int a=0; a< tries; a++) {
            ret = metod2();
        }
        long timeend2 = System.nanoTime();
        System.out.println();


        long t1 = timeend1-timestart;
        long t2 = timeend2-timeend1;
        System.out.println("\ntime 1=["+t1+"]\n     2=["+t2+"]"+
                 "\ndiff=["+Math.abs(t1-t2)+"] percent diff=["+(100d*t2/t1-100)+"]");

    }

    private static boolean metod2() {
        try {
            int val = array[gen.nextInt(2)];
            return true;
        } catch (Exception e) {
            return false;
        }
    }

    private static boolean method1() {
        return array.length < gen.nextInt(2);
    }

}

結果:

JDK 7、日食Run asモード:

time check=[911620628]
       exc=[1192569638]
diff=[280949010] percent diff=[30.818632375220886]

JDK 7、日食Debugモード:

time check=[931243924]
       exc=[651480777121]
diff=[650549533197] percent diff=[69858.12378809143]

デバッグを無効にした場合の速度の低下は、目に見えるものではありますが、それほど重要ではありません。例外のないコードは、約 30% 高速です (false リターンの約 50% に対して)。デバッグモードでの速度低下は驚くべきものです。例外ベースのコードは、通常の単純な配列サイズ チェックよりも約 700 倍遅く実行されます。

例外の哲学

例外の背後にある一般的な考え方は、例外条件を処理する方法を許可することです。この場合、例外的な条件はまったくありません。範囲チェックは、コードの通常の部分にすぎません。その理由だけで、この状況では例外を使用しないでください。

于 2013-09-18T12:50:14.627 に答える