62

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

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

4

15 に答える 15

75

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

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

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

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

于 2010-03-13T17:28:26.840 に答える
34

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

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

両方の最大長は Integer.MAX_VALUE です。これらは配列として内部的に格納され、Java 配列intには長さ疑似フィールドしかないためです。

String複数連結のs とs の間のパフォーマンスの向上StringBufferは非常に重要です。次のテスト コードを実行すると、違いがわかります。Java 6 を搭載した古いラップトップでは、次の結果が得られます。

文字列との連結にかかった時間: 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");
    }
}
于 2010-03-13T17:28:57.640 に答える
24
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
于 2013-03-22T06:54:16.457 に答える
10

文字列は不変クラスです。これは、次のように文字列のインスタンスをインスタンス化すると、次のようになることを意味します。

String str1 = "hello";

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

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

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

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

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

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

于 2011-03-04T16:58:24.520 に答える
4

APIから:

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

于 2011-03-04T16:50:25.550 に答える
2

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

StringBuffer にアクセスする Thread が 1 つしかない場合は、StringBuilder が同期されないため高速であるため、StringBuffer の代わりに StringBuilder を使用する必要があります。

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

于 2010-03-13T17:27:03.447 に答える
2

Reggie Hutchersoによるパフォーマンス String と StringBuffer の比較に関する興味深い回答を見つけました 。

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

これら 2 つのクラスのパフォーマンスの大きな違いは、単純な連結を実行する場合、StringBuffer が String よりも高速であることです。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 オブジェクトを作成し、その追加メソッドを呼び出します。一時的な StringBuffer オブジェクトは場所 10 で作成され、その追加メソッドは場所 23 で呼び出されます。String クラスは不変であるため、StringBuffer を使用する必要があります。連結。

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

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

  1. 位置 0 の String オブジェクト
  2. 位置 10 の StringBuffer オブジェクト
  3. 位置 26 の String オブジェクト

それでは、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 オブジェクトに変換する必要はありません。このコードは、1 つのオブジェクト (StringBuffer) のみを位置 0 に作成します。

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

于 2010-11-23T06:55:49.793 に答える
2

追加操作が証明された後に 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
于 2016-06-23T06:02:18.613 に答える
1

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

AStringBufferは変更可能な文字配列です。String多くの場合、変異が完了すると元に戻ります。

どちらも配列であるため、両方の最大サイズは整数の最大サイズに等しく、2^31-1 です ( JavaDoc を参照してください。との両方についてJavaDocも参照してください)。これは、配列の引数がプリミティブです。(配列を参照してください)。StringStringBuffer.lengthint

于 2010-03-13T17:29:23.257 に答える
1

のフレーバーで多くの文字列連結を行う場合は常に、 AStringBufferまたはその弟で高速な兄弟StringBuilderが優先されます。

string += newString;

または同等に

string = string + newString;

上記の構成は毎回暗黙的に新しい文字列を作成するため、パフォーマンスが大幅に低下し、低下します。StringBuffer/StringBuilderは、動的に拡張可能な と比較するのに最適ですList<Character>

于 2010-03-13T17:29:49.937 に答える
1

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

  • 逆行する()
  • setCharAt()
于 2014-11-20T03:14:56.717 に答える
1

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

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

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

于 2011-03-04T16:50:41.860 に答える
1
String is immutable. 

なんで?ここで確認してください。

StringBuffer is not. It is thread safe. 

いつどの概念を使用するかなどのさらなる質問は、これに続いて理解できます

お役に立てれば。

于 2013-07-25T06:44:01.500 に答える
1

違いは

  1. Stringクラスでのみ+演算子がオーバーロードされます。+演算子を使用して 2 つの String オブジェクトを連結できますが、 StringBufferの場合は連結できません。
  2. StringクラスはObjectクラスの toString()、equals()、hashCode() をオーバーライドしていますが、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. String は不変ですが、StringBuffer は変更可能です。
  6. StringBuffer は同期されますが、String は同期されません。
  7. StringBuffer には組み込みのreverse()メソッドがありますが、String にはありません。
于 2017-01-17T13:28:55.970 に答える
0

パフォーマンスに関しては、 StringBuffer は String よりもはるかに優れています。String オブジェクトに連結を適用するたびに、連結ごとに新しい 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

于 2016-06-11T10:21:34.067 に答える