質問

と仮定して文字列aおよびb:

a += b
a = a.concat(b)

背後にある実装では、その心に何か起きているのかこんなことをしたのだろう。

こちらはconcat decompiledしています。持ってき方など、さすがだなと私が逆コンパイルに + オペレーターとしている。

public String concat(String s) {

    int i = s.length();
    if (i == 0) {
        return this;
    }
    else {
        char ac[] = new char[count + i];
        getChars(0, count, ac, 0);
        s.getChars(0, i, ac, count);
        return new String(0, count + i, ac);
    }
}
役に立ちましたか?

解決

いいえ、必ずしもそうではありません。

まず、わずかな違い意味論。の場合 anull, その a.concat(b) 投げ NullPointerExceptiona+=b 取り扱いまの元の値 a そのなかで null.さらに、 concat() 方法のみを受け入れ String 値が + オペレーターが黙々と変換する引数文字列を使用して toString() 方法。その concat() 方法はより厳格などで受けた。

眺めのフードは、単純なクラス a += b;

public class Concat {
    String cat(String a, String b) {
        a += b;
        return a;
    }
}

現在では分解と javap -c (Sun JDK).がついているものの上場を含む:

java.lang.String cat(java.lang.String, java.lang.String);
  Code:
   0:   new     #2; //class java/lang/StringBuilder
   3:   dup
   4:   invokespecial   #3; //Method java/lang/StringBuilder."<init>":()V
   7:   aload_1
   8:   invokevirtual   #4; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
   11:  aload_2
   12:  invokevirtual   #4; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
   15:  invokevirtual   #5; //Method java/lang/StringBuilder.toString:()Ljava/lang/    String;
   18:  astore_1
   19:  aload_1
   20:  areturn

なので、 a += b に相当する

a = new StringBuilder()
    .append(a)
    .append(b)
    .toString();

concat 法要になります。しかし、文字列の StringBuilder 法勝、少なくともの。

のソースコード StringStringBuilder (およびそのパッケージ-個人の基底クラス)をご用意src.zip を推奨します。できま築char配列のサイズ変更必要に応じて)として捨てるのを作成する場合、最終 String.実際にメモリ割り当てが驚くほど速い。

更新: としてPawel Adamski、性能が変わった最近のホットスポットにする。 javac り出す正確に同じコードが、bytecodeコンパイラの攻略.簡単な試験を完全に失敗したので、全体のコードがスローされます。総括 System.identityHashCodeString.hashCodeStringBuffer コードは、若干です。変更時に次回更新は、ご利用の場合は別のJVM.から @lukaseder, リストホットスポットJVM intrinsics.

他のヒント

Niyaz が正しいももここで注目される特殊+オペレーターの変換が可能であるものの効率化により、Javaコンパイラです。Javaは、StringBuilderのクラスは非スレッドに、安全で変更可能な文字列になります。を行うにあたっ文字列concatenations、Javaコンパイラ黙々に変換します

String a = b + c + d;

String a = new StringBuilder(b).append(c).append(d).toString();

ある大型文字列は大幅に効率化する。私が知る限りでは、こうした事態が起こらないようをご利用の場合concat方法です。

しかし、concatの方法は効率が列は空の文字列を、既存の文字列になります。この場合、JVMは要らない新しいStringオブジェクトをできるだけを返し、既存します。見 のconcat書 確認します。

していただけスーパー-懸念の効率化そのものを使用できる、concat方法が列が空文字列、および利用に+ます。しかし、性能の差は軽微であとからも安心です。

を行った同様の試験を実施してい@様々な映画祭でも多くの賞を受賞すが、以下のループではなく:

String c = a;
for (long i = 0; i < 100000L; i++) {
    c = c.concat(b); // make sure javac cannot skip the loop
    // using c += b for the alternative
}

だけどめっ投げる StringBuilder.append() しています。それぞれの試験した10倍、100k担当者のためします。この結果:

  • StringBuilder 勝手です。の時計の時刻で結果が0での運行しており、最も長いた16ms.
  • a += b 約40000ms(40)用します。
  • concat みが必要で10000ms(10sります。

いdecompiledのクラスの内部または実行を通じてプロファイラな疑い a += b 近くを過ごす多くの時間を新しいオブジェクトの StringBuilder その変換に戻る String.

最も回答はこちらから2008年.見えるものについては、切断のうえ破棄す。私の最新のベンチマークを使ったJMHがJava8 + 周辺には二倍 concat.

私のベンチマーク:

@Warmup(iterations = 5, time = 200, timeUnit = TimeUnit.MILLISECONDS)
@Measurement(iterations = 5, time = 200, timeUnit = TimeUnit.MILLISECONDS)
public class StringConcatenation {

    @org.openjdk.jmh.annotations.State(Scope.Thread)
    public static class State2 {
        public String a = "abc";
        public String b = "xyz";
    }

    @org.openjdk.jmh.annotations.State(Scope.Thread)
    public static class State3 {
        public String a = "abc";
        public String b = "xyz";
        public String c = "123";
    }


    @org.openjdk.jmh.annotations.State(Scope.Thread)
    public static class State4 {
        public String a = "abc";
        public String b = "xyz";
        public String c = "123";
        public String d = "!@#";
    }

    @Benchmark
    public void plus_2(State2 state, Blackhole blackhole) {
        blackhole.consume(state.a+state.b);
    }

    @Benchmark
    public void plus_3(State3 state, Blackhole blackhole) {
        blackhole.consume(state.a+state.b+state.c);
    }

    @Benchmark
    public void plus_4(State4 state, Blackhole blackhole) {
        blackhole.consume(state.a+state.b+state.c+state.d);
    }

    @Benchmark
    public void stringbuilder_2(State2 state, Blackhole blackhole) {
        blackhole.consume(new StringBuilder().append(state.a).append(state.b).toString());
    }

    @Benchmark
    public void stringbuilder_3(State3 state, Blackhole blackhole) {
        blackhole.consume(new StringBuilder().append(state.a).append(state.b).append(state.c).toString());
    }

    @Benchmark
    public void stringbuilder_4(State4 state, Blackhole blackhole) {
        blackhole.consume(new StringBuilder().append(state.a).append(state.b).append(state.c).append(state.d).toString());
    }

    @Benchmark
    public void concat_2(State2 state, Blackhole blackhole) {
        blackhole.consume(state.a.concat(state.b));
    }

    @Benchmark
    public void concat_3(State3 state, Blackhole blackhole) {
        blackhole.consume(state.a.concat(state.b.concat(state.c)));
    }


    @Benchmark
    public void concat_4(State4 state, Blackhole blackhole) {
        blackhole.consume(state.a.concat(state.b.concat(state.c.concat(state.d))));
    }
}

結果:

Benchmark                             Mode  Cnt         Score         Error  Units
StringConcatenation.concat_2         thrpt   50  24908871.258 ± 1011269.986  ops/s
StringConcatenation.concat_3         thrpt   50  14228193.918 ±  466892.616  ops/s
StringConcatenation.concat_4         thrpt   50   9845069.776 ±  350532.591  ops/s
StringConcatenation.plus_2           thrpt   50  38999662.292 ± 8107397.316  ops/s
StringConcatenation.plus_3           thrpt   50  34985722.222 ± 5442660.250  ops/s
StringConcatenation.plus_4           thrpt   50  31910376.337 ± 2861001.162  ops/s
StringConcatenation.stringbuilder_2  thrpt   50  40472888.230 ± 9011210.632  ops/s
StringConcatenation.stringbuilder_3  thrpt   50  33902151.616 ± 5449026.680  ops/s
StringConcatenation.stringbuilder_4  thrpt   50  29220479.267 ± 3435315.681  ops/s

Tomが正しく記述そのもの+オペレーター。するための仮 StringBuilder,追加しますので終了 toString().

しかし、すべての答えをこれまではそれを無視しての効果はホットスポットランタイム最適化.具体的には、これらの一時業務として認識している共通パターンや効率的なマシンコードで実行します。

@様々な映画祭でも多くの賞を受賞:まった マイクロベンチマーク;現代のJVMのではない有効な方にプロファイルのコードです。

その理由実行時間の最適化問題の多くはこれらの違いコードも含むオブジェクトの創出--完全に一度の異なるホットスポットを返します。のようにはプロファイリングコード in situ.

最後に、これらすべての方法として非常に早いです。これまでのプログラムの場合は早期の最適化。するコード文字列を連結く、取得の最大速くなる事業者を選ぶと共に、やむを得ない事由によりアルゴリズムを使う!

かつ簡単な実験をしていますか?使用以下のコード:

long start = System.currentTimeMillis();

String a = "a";

String b = "b";

for (int i = 0; i < 10000000; i++) { //ten million times
     String c = a.concat(b);
}

long end = System.currentTimeMillis();

System.out.println(end - start);
  • "a + b" 版の実行 2500ms.
  • a.concat(b) 実行され 1200ms.

試験ます。の concat() 版の実行った半分の時間の平均値。

この結果は、驚きで concat() メソッドは常に新しい文字列を返します"new String(result)".ことがよく知られる:

String a = new String("a") // more than 20 times slower than String a = "a"

なぜか、コンパイラでの最適な文字列の作成"a+bの"コードであることを知りなので、常に結果を同一の文字列?すな新しい文字列。だということなの算書、試験ます。

基本的に重要な差異+の concat 方法。

  1. をご利用の場合 concat メソッドをすることができる文字列連結した場合 + オペレーターで連結の文字列のデータ型でもかまいません。

    例えば:

    String s = 10 + "Hello";
    

    この場合、出力 10Hello.

    String s = "I";
    String s1 = s.concat("am").concat("good").concat("boy");
    System.out.println(s1);
    

    上記の場合は、提供を二つの文字列必須です。

  2. 第二に、主な違いは +concat は:

    例1: ることもあり、concat同じ文字列 concat このようにオペレーター

    String s="I";
    String s1=s.concat("am").concat("good").concat("boy");
    System.out.println(s1);
    

    この場合の計数を作成したオブジェクトのプールは7のようになります:

    I
    am
    good
    boy
    Iam
    Iamgood
    Iamgoodboy
    

    例2:

    波長と異なっているconcatinate同じ文字列によ + オペレーター

    String s="I"+"am"+"good"+"boy";
    System.out.println(s);
    

    上記の場合の合計数を作成したオブジェクトは5です。

    実際におconcatinateの文字列によ + オペレーターそのまま維持するStringBufferを行うクラス同様の処理は以下のとおり

    StringBuffer sb = new StringBuffer("I");
    sb.append("am");
    sb.append("good");
    sb.append("boy");
    System.out.println(sb);
    

    このようにこれらの成果をみた。

うーんこれらの基本的な違い +concat 方法。お楽しみ:)

完全性のためになかったり、のの定義は、'+'オペレーターの 環太平洋のSE8 15.18.1:

だけのオペランドが表現型の文字列、文字列 変換(§5.1.11)について興味があるというその他のオペランドを製造す 文字列ます。

結果の文字列の連結"があるStringオブジェクト を連結した文字列を二つの被演算子の文字列です。文字 左側のオペランド優先の文字は右 オペランドが新たに作成された文字列になります。

文字列オブジェクトを新規に作成した(§12.5)ない限り、表現である 一定の表現§15.28).

実施については、環太平洋というの

実装が実行するように変換と連結 一つのステップを作成しないよう、その後破棄中間 文字列オブジェクトです。パフォーマンスが向上しますの繰り返し文字列 結合、JavaコンパイラのStringBufferのクラスまたは 同様の手法を減らの中間の文字列オブジェクト 自分が作成した評価式です。

のためのプリミティブ型は、実装にも最適の 創造のラッパーオブジェクトに変換から直接プリミティブ タイプを文字列になります。

からのJavaコンパイラのStringBufferのクラスまたは同様の手法の削減、コンパイラを作り出すことのできる異なるバイトコードです。

+オペレーター での間に文字列、文字列、char、integer、ダブルまたはfloatデータ型の値です。それだけで変換した値を文字列表現を前連結した.

concatオペレーター でなければできない、との文字列です。でチェックのためのデータ型に互換性およびスローエラーなければならない。

それ以外に、お客様よりご提供いただいたい同じもの。

ないと思います。

a.concat(b) 行列を文字列と思い、実施に変わらないんだよねっと早くからjavaます。の + 操作の実装に依存してJavaバージョンおよびコンパイラです。現在 + を使用して実現し StringBuffer の運営とが可能です。もしかし今後、この変わります。以前のバージョンのjava + 操作文字列の長さで製作中。

を行っていたのでしょう += を使用して実現し + 同じように最適化されています。

利用の場合は、速度が低下する文字列の長さの増加が、concatの速度はより安定した、最良のオプションを使用してStringBuilderのクラスは安定した速います。

か理解できるのはいかがでしょうか。もっニーズに合わせたサービスの創造の長い文字列を使用StringBuilder()やappend()は、スピードが高速に受け入れられない。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top