web-dev-qa-db-ja.com

JavaのStringとStringBufferの違いは何ですか?

JavaのStringとStringBufferの違いは何ですか?

文字列の最大サイズはありますか?

63
Praveen

Stringは、変更できない文字列(読み取り専用で不変)を操作するために使用されます。

StringBufferは、変更可能な文字を表すために使用されます。

パフォーマンスの面では、StringBufferは連結を実行するときに高速です。これは、Stringを連結すると、Stringが不変であるため、毎回(内部的に)新しいオブジェクトを作成しているためです。

StringBuilderを使用することもできます。これは、StringBufferと似ていますが、同期されない点が異なります。これらのいずれかの最大サイズはInteger.MAX_VALUE(231 -1 = 2,147,483,647)または最大ヒープサイズを2で割った値( Java文字列に含めることができる文字数 を参照)。詳細情報 こちら

75
Vivin Paliath

Stringは不変です。つまり、作成されたときは変更できません。

StringBuffer(またはその非同期のいとこStringBuilder)は、途中でたくさんのStringsを構築するパフォーマンスオーバーヘッドなしで文字列を1つずつ構築する必要がある場合に使用されます。

両方の最大長はInteger.MAX_VALUEです。これらは内部的に配列として格納されており、Java配列には長さの擬似フィールドにintしかありません。

複数の連結に対するStringsとStringBuffersの間のパフォーマンスの改善は非常に重要です。次のテストコードを実行すると、違いがわかります。 Java 6を使用した古代のラップトップでは、次の結果が得られます。

 Stringとの連結にかかった時間:1781ms 
 StringBufferとの連結にかかった時間:0ms 
public class Concat
{
    public static String concatWithString()
    {
        String t = "Cat";
        for (int i=0; i<10000; i++)
        {
            t = t + "Dog";
        }
        return t;
    }
    public static String concatWithStringBuffer()
    {
        StringBuffer sb = new StringBuffer("Cat");
        for (int i=0; i<10000; i++)
        {
            sb.append("Dog");
        }
        return sb.toString();
    }
    public static void main(String[] args)
    {
        long start = System.currentTimeMillis();
        concatWithString();
        System.out.println("Concat with String took: " + (System.currentTimeMillis() - start) + "ms");
        start = System.currentTimeMillis();
        concatWithStringBuffer();
        System.out.println("Concat with StringBuffer took: " + (System.currentTimeMillis() - start) + "ms");
    }
}
34
Simon Nickerson
String                                          StringBuffer

Immutable                                       Mutable
String s=new String("karthik");                StringBuffer sb=new StringBuffer("karthik")
s.concat("reddy");                             sb.append("reddy");
System.out.println(s);                         System.out.println(sb);
O/P:karthik                                    O/P:karthikreddy

--->once we created a String object            ---->once we created a StringBuffer object
we can't perform any changes in the existing  we can perform any changes in the existing
object.If we are trying to perform any        object.It is nothing but mutablity of 
changes with those changes a new object       of a StrongBuffer object
will be created.It is nothing but Immutability
of a String object

Use String--->If you require immutabilty
Use StringBuffer---->If you require mutable + threadsafety
Use StringBuilder--->If you require mutable + with out threadsafety

String s=new String("karthik");
--->here 2 objects will be created one is heap and the other is in stringconstantpool(scp) and s is always pointing to heap object

String s="karthik"; 
--->In this case only one object will be created in scp and s is always pointing to that object only
24
Karthik Reddy

文字列は不変のクラスです。つまり、次のような文字列のインスタンスをインスタンス化すると、

String str1 = "hello";

メモリ内のオブジェクトは変更できません。代わりに、新しいインスタンスを作成し、古い文字列をコピーして、この例のように他のものを追加する必要があります。

String str1 = "hello";
str1 = str1 + " world!";

実際に起こっていることは、既存のstr1オブジェクトを更新していないということです...新しいメモリをすべて再割り当てし、「hello」データをコピーし、「world!」を追加しています。最後に、この新しいメモリを指すようにstr1参照を設定します。したがって、実際にはこのように見えます。

String str1 = "hello";
String str2 = str1 + " world!";
str1 = str2;

したがって、この「コピー+貼り付けとメモリ内のデータの移動」プロセスは、特に再帰的に繰り返し実行すると非常にコストがかかる可能性があります。

StringBuilderを何度も繰り返し使用しなければならない状況にあるとき。可変であり、現在の配列の最後に文字列を追加できます。これは[成長する配列]によって戻されるためです(実際のデータ構造である場合は100%ではなく、リストになる可能性があります)。

10
Feisty Mango

API: から

スレッドセーフで変更可能な文字のシーケンス。文字列バッファは文字列に似ていますが、変更できます。どの時点でも特定の文字シーケンスが含まれていますが、特定のメソッド呼び出しを使用してシーケンスの長さと内容を変更できます。

4
posdef

Reggie HutchersoSourceによるStringとStringBufferのパフォーマンスの比較に興味のある答えが見つかりました: http://www.javaworld.com/javaworld/jw -03-2000/jw-0324-javaperf.html

JavaはStringBufferクラスとStringクラスを提供し、Stringクラスは変更できない文字列を操作するために使用されます。簡単に言えば、String型のオブジェクトは読み取り専用で不変です。 StringBufferクラスは、変更可能な文字を表すために使用されます。

これら2つのクラスのパフォーマンスの大きな違いは、単純な連結を実行する場合、StringBufferはStringよりも高速であることです。文字列操作コードでは、文字列は定期的に連結されます。 Stringクラスを使用すると、通常、連結は次のように実行されます。

 String str = new String ("Stanford  ");
 str += "Lost!!";

StringBufferを使用して同じ連結を実行する場合、次のようなコードが必要になります。

 StringBuffer str = new StringBuffer ("Stanford ");
 str.append("Lost!!");

開発者は通常、連結にappendメソッドを使用する2番目の例は、+演算子を使用して2つのStringオブジェクトを連結する最初の例よりもコストが高いと考えているため、上記の最初の例の方が効率的であると考えています。

+演算子は無害に見えますが、生成されたコードにはいくつかの驚きがあります。連結にStringBufferを使用すると、実際にはStringを使用するよりも大幅に高速なコードを生成できます。なぜそうなのかを知るには、2つの例から生成されたバイトコードを調べる必要があります。 Stringを使用した例のバイトコードは次のようになります。

0 new #7 <Class Java.lang.String>
3 dup 
4 ldc #2 <String "Stanford ">
6 invokespecial #12 <Method Java.lang.String(Java.lang.String)>
9 astore_1
10 new #8 <Class Java.lang.StringBuffer>
13 dup
14 aload_1
15 invokestatic #23 <Method Java.lang.String valueOf(Java.lang.Object)>
18 invokespecial #13 <Method Java.lang.StringBuffer(Java.lang.String)>
21 ldc #1 <String "Lost!!">
23 invokevirtual #15 <Method Java.lang.StringBuffer append(Java.lang.String)>
26 invokevirtual #22 <Method Java.lang.String toString()>
29 astore_1

0〜9の位置のバイトコードは、コードの最初の行に対して実行されます。

 String str = new String("Stanford ");

次に、位置10から29のバイトコードが連結のために実行されます。

 str += "Lost!!";

ここで面白くなってきます。連結用に生成されたバイトコードはStringBufferオブジェクトを作成し、そのappendメソッドを呼び出します。一時的なStringBufferオブジェクトは場所10で作成され、そのappendメソッドは場所23で呼び出されます。連結。

連結がStringBufferオブジェクトで実行された後、文字列に変換し直す必要があります。これは、26の場所でtoStringメソッドを呼び出すことで実行されます。このメソッドは、一時的なStringBufferオブジェクトから新しいStringオブジェクトを作成します。この一時StringBufferオブジェクトの作成と、その後のStringオブジェクトへの変換は非常に高価です。

要約すると、上記の2行のコードにより、3つのオブジェクトが作成されます。

  1. ロケーション0のStringオブジェクト
  2. ロケーション10のStringBufferオブジェクト
  3. 場所26の文字列オブジェクト

ここで、StringBufferを使用した例で生成されたバイトコードを見てみましょう。

0 new #8 <Class Java.lang.StringBuffer>
3 dup
4 ldc #2 <String "Stanford ">
6 invokespecial #13 <Method Java.lang.StringBuffer(Java.lang.String)>
9 astore_1
10 aload_1 
11 ldc #1 <String "Lost!!">
13 invokevirtual #15 <Method Java.lang.StringBuffer append(Java.lang.String)>
16 pop

0〜9の位置のバイトコードは、コードの最初の行に対して実行されます。

 StringBuffer str = new StringBuffer("Stanford ");

次に、連結のために10〜16の位置のバイトコードが実行されます。

 str.append("Lost!!");

最初の例と同様に、このコードはStringBufferオブジェクトのappendメソッドを呼び出します。ただし、最初の例とは異なり、一時的なStringBufferを作成して、それをStringオブジェクトに変換する必要はありません。このコードは、位置0にStringBufferというオブジェクトを1つだけ作成します。

結論として、StringBuffer連結はString連結よりもかなり高速です。明らかに、可能な場合はこのタイプの操作でStringBuffersを使用する必要があります。 Stringクラスの機能が必要な場合は、連結にStringBufferを使用してから、Stringへの1つの変換を実行することを検討してください。

2
NguyenDat

StringBufferは、多くの文字列から単一の文字列を作成するために使用されます。ループ内で文字列の一部を追加する場合。

StringBuilderは同期されていないため高速であるため、StringBufferにアクセスするスレッドが1つだけの場合は、StringBufferではなくStringBuilderを使用する必要があります。

知る限り、言語としてのJavaには文字列サイズの上限はありませんが、JVMにはおそらく上限があります。

2
Thomas Lötzer

追加操作も証明された後、String/StringBufferオブジェクトのハッシュコードを出力することにより、同じStringオブジェクトを使用するのではなく、Stringオブジェクトが毎回新しい値で内部的に再作成されます。

public class MutableImmutable {

/**
 * @param args
 */
public static void main(String[] args) {
    System.out.println("String is immutable");
    String s = "test";
    System.out.println(s+"::"+s.hashCode());
    for (int i = 0; i < 10; i++) {
        s += "tre";
        System.out.println(s+"::"+s.hashCode());
    }

    System.out.println("String Buffer is mutable");

    StringBuffer strBuf = new StringBuffer("test");
    System.out.println(strBuf+"::"+strBuf.hashCode());
    for (int i = 0; i < 10; i++) {
        strBuf.append("tre");
        System.out.println(strBuf+"::"+strBuf.hashCode());
    }

 }

}

出力:ハッシュコードとともにオブジェクト値を出力します

    String is immutable
    test::3556498
    testtre::-1422435371
    testtretre::-1624680014
    testtretretre::-855723339
    testtretretretre::2071992018
    testtretretretretre::-555654763
    testtretretretretretre::-706970638
    testtretretretretretretre::1157458037
    testtretretretretretretretre::1835043090
    testtretretretretretretretretre::1425065813
    testtretretretretretretretretretre::-1615970766
    String Buffer is mutable
    test::28117098
    testtre::28117098
    testtretre::28117098
    testtretretre::28117098
    testtretretretre::28117098
    testtretretretretre::28117098
    testtretretretretretre::28117098
    testtretretretretretretre::28117098
    testtretretretretretretretre::28117098
    testtretretretretretretretretre::28117098
    testtretretretretretretretretretre::28117098
2
DeepaGanesh

これは大きな差別化要因ではないことを理解していますが、今日は、StringBuffer(およびStringBuilder)がStringにはない興味深いメソッドを提供していることに気付きました。

  • 逆()
  • setCharAt()
1
jaydeep

Stringは不変の文字配列です。

StringBufferは可変文字配列です。多くの場合、変更が完了するとStringに変換されます。

両方が配列であるため、両方の最大サイズは整数の最大サイズである2 ^ 31-1に等しくなります( JavaDoc を参照してください。また、両方のJavaDocを確認してくださいStringおよびStringBuffer)。これは、配列の.length引数がプリミティブintであるためです。 ( Arrays を参照)。

1
Pindatjuh

StringBufferまたはそのより若くて速い兄弟 StringBuilder は、多くの文字列の連結を行う場合は常に

string += newString;

または同等に

string = string + newString;

上記の構成は暗黙的にnew文字列を作成するため、毎回巨大なパフォーマンスとドロップになります。 StringBuffer/StringBuilderは、動的に拡張可能なList<Character>と比較するのに最適です。

1
BalusC

違いは

  1. String classでのみ+演算子がオーバーロードされます。 +演算子を使用して2つのStringオブジェクトを連結できますが、StringBufferの場合はできません。
  2. StringクラスはtoString()、equals()、hashCode()をオーバーライドしますObjectクラスですが、StringBufferはtoString()のみをオーバーライドします。

    String s1 = new String("abc");
    String s2 = new String("abc");
    System.out.println(s1.equals(s2));  // output true
    
    StringBuffer sb1 = new StringBuffer("abc");
    StringBuffer sb2 = new StringBuffer("abc");
    System.out.println(sb1.equals(sb2));  // output false
    
  3. StringクラスはSerializableComparableの両方ですが、StringBufferSerializableのみです。

    Set<StringBuffer> set = new TreeSet<StringBuffer>();
    set.add(sb1);
    set.add(sb2);
    System.out.println(set);  // gives ClassCastException because there is no Comparison mechanism
    
  4. new演算子の有無にかかわらずStringオブジェクトを作成できますが、StringBufferオブジェクトはnew演算子を使用してのみ作成できます。

  5. 文字列は不変ですが、StringBufferは可変です。
  6. StringBufferは同期されますが、Stringは同期されません。
  7. StringBufferには組み込みのreverse()メソッドがありますが、Stringにはありません。
1
Arun Sudhakaran

文字列は不変です。つまり、文字列に対して操作を実行すると、実際にはまったく新しい文字列が作成されます。

StringBuffer は可変であり、追加したり、長さを0にリセットしたりできます。

実際には、コンパイラは文字列の連結中にStringBufferを使用しているようです パフォーマンス上の理由から

1
Matthew Willis
String is immutable. 

どうして? こちら を確認してください。

StringBuffer is not. It is thread safe. 

this に続いて、どの概念を使用すべきか、その他の概念をいつ使用するかなどのさらなる質問を理解できます。

お役に立てれば。

1
roger_that

パフォーマンスに関するStringBufferはStringよりもはるかに優れています。というのは、文字列オブジェクトに連結を適用すると、連結ごとに新しい文字列オブジェクトが作成されるからです。

プリンシパルルール:文字列は不変(変更不可)であり、StringBufferは可変(変更可能)

これは、パフォーマンスの違いを取得するプログラムによる実験です

public class Test {

  public static int LOOP_ITERATION= 100000;

  public static void stringTest(){
    long startTime = System.currentTimeMillis();
    String string = "This";
    for(int i=0;i<LOOP_ITERATION;i++){
        string = string+"Yasir";
    }

    long endTime = System.currentTimeMillis();
    System.out.println(endTime - startTime);    
  }

  public static void stringBufferTest(){
    long startTime = System.currentTimeMillis();
    StringBuffer stringBuffer = new StringBuffer("This");
    for(int i=0;i<LOOP_ITERATION;i++){
        stringBuffer.append("Yasir");
    }

    long endTime = System.currentTimeMillis();
    System.out.println(endTime - startTime);
  }

  public static void main(String []args){
    stringTest()
    stringBufferTest(); 
  }
 }

文字列の出力は私のマシンにあります 14800

StringBufferの出力は私のマシンにあります 14