2017-08-30 12 views
1

文字列を複数回使用したいのですが、文字が必要なときはいつでもstring.charAt()を使用する方がいいかと思います。 string.toCharArray()を使用し、indexを使用して配列内の文字にアクセスします。だから私は簡単なベンチマークプログラムを書いた。Javaの文字列の文字を繰り返し使用するより良い方法

static int[] loops = new int[]{10000, 100000, 1000000}; 

static void useCharAt(String s){ 
    int sum = 0; 
    for(int loop : loops) { 
     long start = System.currentTimeMillis(); 
     for (int i = 0; i < loop; i++) { 
      for (int j = 0; j < s.length(); j++) { 
       sum += s.charAt(j); 
      } 
     } 
     System.out.println("string size is " + s.length() + ", loop size is "+loop+", charAt() costs " + (System.currentTimeMillis() - start) + " ms"); 
    } 
} 

static void useArray(String s){ 
    char[] arr= s.toCharArray(); 
    int sum = 0; 
    for(int loop : loops) { 
     long start = System.currentTimeMillis(); 
     for (int i = 0; i < loop; i++) { 
      for (char c : arr) { 
       sum += c; 
      } 
     } 
     System.out.println("string size is " + s.length() + ", loop size is "+loop+", array costs " + (System.currentTimeMillis() - start) + " ms"); 
    } 
} 

public static void main(String[] args){ 
    StringBuilder sb = new StringBuilder(); 
    int strLen[] = new int[]{1000, 5000, 10000}; 
    for(int len : strLen) { 
     sb.setLength(0); 
     for(int i = 0; i < len; i++) sb.append('a'); 
     String s = sb.toString(); 
     useArray(s); 
     useCharAt(s); 
    } 
} 

と結果がのcharAt()は、配列との直接アクセスよりも遅くなり、なぜかしら

string size is 1000, loop size is 10000, array costs 10 ms 
string size is 1000, loop size is 100000, array costs 60 ms 
string size is 1000, loop size is 1000000, array costs 495 ms 
string size is 1000, loop size is 10000, charAt() costs 14 ms 
string size is 1000, loop size is 100000, charAt() costs 184 ms 
string size is 1000, loop size is 1000000, charAt() costs 1649 ms 

string size is 5000, loop size is 10000, array costs 23 ms 
string size is 5000, loop size is 100000, array costs 232 ms 
string size is 5000, loop size is 1000000, array costs 2277 ms 
string size is 5000, loop size is 10000, charAt() costs 82 ms 
string size is 5000, loop size is 100000, charAt() costs 828 ms 
string size is 5000, loop size is 1000000, charAt() costs 8202 ms 

string size is 10000, loop size is 10000, array costs 44 ms 
string size is 10000, loop size is 100000, array costs 458 ms 
string size is 10000, loop size is 1000000, array costs 4559 ms 
string size is 10000, loop size is 10000, charAt() costs 166 ms 
string size is 10000, loop size is 100000, charAt() costs 1626 ms 
string size is 10000, loop size is 1000000, charAt() costs 16280 ms 

のですか?私はchatAt()の実装をチェックし、配列の直接アクセスメソッドとの違いは何もわかりません。

public char charAt(int index) { 
    if ((index < 0) || (index >= value.length)) { 
     throw new StringIndexOutOfBoundsException(index); 
    } 
    return value[index]; 
} 
+1

関数呼び出しコスト+追加の境界チェック。すべてがかなり妥当に見えます。 – algrid

+0

[Javaで正しいマイクロベンチマークを書くにはどうすればいいですか?](https://stackoverflow.com/questions/504103/how-do-i-write-a-correct-micro-benchmark-in-java) –

+0

ありがとうあなたの両方のコメントのために!私はいくつかの記事とチュートリアルを見て、問題を理解し始めました。 –

答えて

2

toCharArray()を使用すると、Stringの内部配列がコピーされる初期コストが発生します。

その後、配列への単純なアクセス(値が返されたときにもcharAt()で起こる暗黙的な境界チェックを使用)です。 charAt()の呼び出しには、関数呼び出しと重複した境界チェック(ArrayIndexOutOfBoundsExceptionの代わりにStringIndexOutOfBoundsExceptionをスローする)のコストが伴います。

この影響は非常によく知られており、すでにJavaパフォーマンスブックの初期に記載されています。

文字列内の1文字にしかアクセスできない場合は、charAt()を使用する方がよいでしょう。より多くの、またはすべての文字にアクセスし、文字列が長くなる可能性がある場合は、toCharArray()を使用するほうが効果的です。

関連する問題