web-dev-qa-db-ja.com

整数を文字列に連結-パフォーマンスとメモリの観点から文字列リテラルまたはプリミティブを使用しますか?

オプション1:

String newStr = someStr + 3 + "]";

オプション2:

String newStr = someStr + "3" + "]";

パフォーマンス、メモリ、および一般的な慣行に関して、どのオプションが優れていますか?コードのメモリ使用量とそのパフォーマンスを測定するために使用できる推奨ツール/方法は何ですか(開始時間と終了時間を測定して差を計算する以外に)

9
user1739658

最初は次のようになります:

StringBuilder sb = new StringBuilder (String.valueOf (someStr));
sb.append (3);
sb.append ("]");
String newStr = sb.toString ();

2番目は次のようになります。

StringBuilder sb = new StringBuilder (String.valueOf (someStr));
sb.append ("3");
sb.append ("]");
String newStr = sb.toString ();

これは分解です:

public String foo (String someStr)
{
    String newStr = someStr + 3 + "]";
    return newStr;
}

public String bar (String someStr)
{
    String newStr = someStr + "3" + "]";
    return newStr;
}

public Java.lang.String foo(Java.lang.String);
Code:
   0: new           #16                 // class Java/lang/StringBuilder
   3: dup
   4: aload_1
   5: invokestatic  #18                 // Method Java/lang/String.valueOf:(Ljava/lang/Object;)Ljava/lang/String;
   8: invokespecial #24                 // Method Java/lang/StringBuilder."<init>":(Ljava/lang/String;)V
  11: iconst_3
  12: invokevirtual #27                 // Method Java/lang/StringBuilder.append:(I)Ljava/lang/StringBuilder;
  15: ldc           #31                 // String ]
  17: invokevirtual #33                 // Method Java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
  20: invokevirtual #36                 // Method Java/lang/StringBuilder.toString:()Ljava/lang/String;
  23: astore_2
  24: aload_2
  25: areturn

public Java.lang.String bar(Java.lang.String);
Code:
   0: new           #16                 // class Java/lang/StringBuilder
   3: dup
   4: aload_1
   5: invokestatic  #18                 // Method Java/lang/String.valueOf:(Ljava/lang/Object;)Ljava/lang/String;
   8: invokespecial #24                 // Method Java/lang/StringBuilder."<init>":(Ljava/lang/String;)V
  11: ldc           #44                 // String 3
  13: invokevirtual #33                 // Method Java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
  16: ldc           #31                 // String ]
  18: invokevirtual #33                 // Method Java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
  21: invokevirtual #36                 // Method Java/lang/StringBuilder.toString:()Ljava/lang/String;
  24: astore_2
  25: aload_2
  26: areturn
11

両方の間に目立った違いはありません。最も論理的で読みやすいものを使用してください。私は使うだろう

String newStr = someStr + "3]";
7
JB Nizet

私は Jprofiler を、多くのメモリの問題を見つけるのに役立つ素晴らしいJavaアプリケーションプロファイリングツールとしてお勧めします。

特にデスクトップアプリケーションの場合、オプション1と2のメモリ使用量に大きな違いはないと思います。

3
Simon

SomeStringが定数であると仮定すると、両方とも定数式であり、コンパイル時に評価されます。それらは、同じクラスファイルと実行時の動作になります。

ソース: Java言語仕様 書き込み:

コンパイル時の定数式とは、プリミティブ型の値または文字列が突然完了せず、以下のみを使用して構成される式を表す式です。

  • プリミティブ型のリテラルと文字列型のリテラル(§3.10.1、§3.10.2、§3.10.3、§3.10.4、§3.10.5)

  • 加法演算子+および-(§15.18)

  • ...

String型のコンパイル時定数式は、メソッド「String.intern」を使用して一意のインスタンスを共有するために、常に「インターン」されます。

SomeStringが定数でない場合、最近のほとんどのコンパイラはStringBuilderを使用します。これは、Java言語仕様により、明示的に 許可 です。

文字列連結の結果は、2つのオペランド文字列を連結したStringオブジェクトへの参照です。新しく作成された文字列では、左側のオペランドの文字が右側のオペランドの文字の前にあります。

Stringオブジェクトは、式がコンパイル時の定数式(§15.28)でない限り、新しく作成されます(§12.5)。

実装は、中間のStringオブジェクトの作成と破棄を回避するために、変換と連結を1つのステップで実行することを選択できます。繰り返し文字列連結のパフォーマンスを向上させるために、Javaコンパイラは、StringBufferクラスまたは同様の手法を使用して、式の評価によって作成される中間のStringオブジェクトの数を減らすことができます。

プリミティブ型の場合、実装は、プリミティブ型から文字列に直接変換することにより、ラッパーオブジェクトの作成を最適化することもできます。

2
meriton

文字列を連結するたびに、連結ごとに文字列の新しいコピーが作成され、両方の文字列が一度に1文字ずつコピーされます。これにより、O(n2)(マクダウェル)。

パフォーマンスを向上させたい場合は、

StringBuilder

そのコンストラクタの1つは次の構文を持っています:

public StringBuilder(int size); //Contains no character. Initial capacity of 'size'. 

StringBuilder(文字の可変シーケンス。文字列は不変であることを忘れないでください)は、すべての文字列のサイズ変更可能な配列を作成するだけでこの問題を解決するのに役立ちます。必要な場合にのみそれらを文字列にコピーします(McDowell)。

StringBuilder str = new StringBuilder(0);
str.append(someStr);
str.append(3);
str.append("]");

参照:

マクダウェル、ゲイル・ラークマン。コーディングのインタビュー、第6版のクラッキング。印刷します。

「Stringbuilder(Java Platform SE 8)」。 Docs.Oracle.com。 N.p.、2016。ウェブ。 2016年6月4日。

0
fonji