1. ホーム
  2. java

[解決済み] 文字列の連結:concat()と "+"演算子の比較

2022-03-17 21:01:43

質問

文字列a,bとする。

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

裏を返せば、同じものなのでしょうか?

参考までにconcatをデコンパイルしたものがこちらです。を逆コンパイルできるようにしたいです。 + 演算子が何をするのかを見てみましょう。

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) を投げます。 NullPointerException しかし a+=b の元の値を扱います。 a であるかのように null . さらに concat() メソッドは String の値であるのに対し + 演算子は、黙って引数を 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 (およびそのパッケージ非公開の基本クラス)は、Sun JDK の src.zip で入手できます。char 配列を構築し(必要に応じてサイズを変更し)、最後の String . 実際には、メモリの確保は驚くほど高速に行われます。

更新してください。 Pawel Adamskiが指摘するように、最近のHotSpotではパフォーマンスが変化しているようです。 javac は全く同じコードを生成しますが、バイトコードコンパイラが不正を行います。単純なテストは、コード本体全体が捨てられてしまうので、完全に失敗する。まとめ System.identityHashCode (ただし String.hashCode を表示します。 StringBuffer のコードが若干有利です。次のアップデートがリリースされたとき、または別のJVMを使用したときに変更される可能性があります。より ルカシーダー , HotSpot JVM intrinsics の一覧です。 .