web-dev-qa-db-ja.com

文字列ビルダーと文字列連結

純粋な文字列連結よりも文字列ビルダーを使用する利点とトレードオフは何ですか?

new StringBuilder(32).append(str1)
                     .append(" test: ")
                     .append(val)
                     .append(" is changed")
                     .toString();

対言う

str1 + " test: " + val + " is changed".

str1はランダムな10文字の文字列です。 str2はランダムな8文字の文字列です。

27
Chun ping Wang

特定の例では、コンパイラは内部でStringBuildersを使用して文字列の連結を行うため、なし。ただし、連結がループで発生した場合、コンパイラはいくつかのStringBuilderおよびStringオブジェクトを作成できます。例えば:

String s= "" ;
for(int i= 0 ; i < 10 ; i++ )
    s+= "a" ;

上記の行3が実行されるたびに、新しいStringBuilderオブジェクトが作成され、sの内容が追加され、「a」が追加され、その後StringBuilderが文字列に変換されますsに割り当てられます。合計10 StringBuildersおよび10 Strings。

逆に、

StringBuilder sb= new StringBuilder() ;
for(int i= 0 ; i < 10 ; i++ )
    sb.append( "a" );
String s= sb.toString() ;

StringBuilderと1 Stringのみが作成されます。

この主な理由は、最初のループが2番目のループと同等であり、より効率的な(バイト)コードを生成することをコンパイラが十分に理解できないためです。より複雑なケースでは、最も賢いコンパイラーでさえ知ることは不可能です。この最適化が絶対に必要な場合は、StringBuildersを明示的に使用して手動で導入する必要があります。

52
Mario Rossi

簡単な答えはパフォーマンスです。ネイティブのStringクラスを使用している場合、不変の文字列を操作します。つまり、

  String line = "Java";
  String sufix = " is awesome";
  line = line + sufix;

2つの文字列「Java」と「is awesome」を作成し、前の2つ(「Java」と「is awesome」)から新しい3番目の文字列「Java is awesome」を作成します。アプリで使用されなくなったため)。それは遅い解決策です。

より高速なソリューションは、文字列をマージするためのバッファ(その名前から明らかな)を提供するスマートアルゴリズムを介して、結果として連結プロセス中に初期文字列を削除しないStringBufferクラスのアプライアンスです。

単一のスレッドアプリケーション(複数のスレッドが同じオブジェクトにアクセスする同時実行性の問題はありません)を記述する場合、初期StringBufferクラスよりも高速なStringBuilderを適用することをお勧めします。

5
user2487119