سؤال

ما هو الفرق بين سلسلة و stringbuffer في جافا؟

هل هناك أقصى حجم لسلسلة؟

هل كانت مفيدة؟

المحلول

String يستخدم لمعالجة سلاسل الأحرف التي لا يمكن تغييرها (للقراءة فقط وغير قابلة للتطبيق).

StringBuffer يستخدم لتمثيل الأحرف التي يمكن تعديلها.

أداء الحكمة، StringBuffer هو أسرع عند أداء الملعات. هذا لأنه عندما تسقط String, ، أنت تقوم بإنشاء كائن جديد (داخلي) في كل مرة String غير ثابت.

تستطيع ايضا استخذام StringBuilder وهو ما يشبه StringBuffer باستثناء أنها غير متزامنة. الحد الأقصى للحجم لأي من هذه Integer.MAX_VALUE (231 - 1 = 2،147،483،647) أو أقصى حجم الكومة مقسوما على 2 (انظر كم عدد الأحرف التي يمكن أن تكون سلسلة جافا؟). معلومات اكثر هنا.

نصائح أخرى

أ String غير ثابت، أي عندما يتم إنشاؤه، لا يمكن تغييره أبدا.

أ StringBuffer (أو ابن عمه غير المتزامن StringBuilder) يستخدم عند الحاجة إلى بناء قطعة سلسلة من قطعة دون أداء النفقات العامة لبناء الكثير من القليل StringS على طول الطريق.

الحد الأقصى للطول كلاهما هو Integer.max_Value، لأنها يتم تخزينها داخليا كصفيفات، ومصفوفات Java لديها فقط int لطول حقل الزائفة.

تحسين الأداء بين Stringرمل StringBufferS للحصول على سلسلة متعددة مهم للغاية. إذا قمت بتشغيل رمز الاختبار التالي، فسترى الفرق. على جهاز الكمبيوتر المحمول القديم مع Java 6، أحصل على هذه النتائج:

concat مع سلسلة استغرق: 1781ms concat مع 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");
    }
}
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

السلسلة هي فئة ثابتة. هذا يعني أنه بمجرد إنشاء مثيل سلسلة مثل ذلك:

String str1 = "hello";

لا يمكن تغيير الكائن في الذاكرة. بدلا من ذلك، سيتعين عليك إنشاء مثيل جديد، انسخ السلسلة القديمة وإلحاق أي شيء آخر كما هو الحال في هذا المثال:

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

ما يحدث حقا سماع هو أننا لا نقوم بتحديث كائن Str1 الحالي ... نحن إعادة تخصيص الذاكرة الجديدة معا، ونسخ البيانات "مرحبا" وإلحاق "العالم!" حتى النهاية، ثم قم بإعداد مرجع Str1 للإشارة إلى هذه الذاكرة الجديدة. لذلك يبدو حقا أكثر مثل هذا تحت غطاء محرك السيارة:

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

لذلك يتبع أن هذه "نسخ + لصق ونقل الأشياء في الذاكرة" يمكن أن تكون مكلفة للغاية إذا تم تنفيذها بشكل متكرر بشكل خاص.

عندما تكون في هذه الحالة من الاضطرار إلى القيام بأشياء أكثر من ذلك، استخدم StringBuilder. إنه قابل للتغيير ويمكن إلحاق الأوتار حتى نهاية واحدة الحالية لأنه يعود من قبل [مجموعة متنامية] (وليس 100٪ إذا كان هذا هو بنية البيانات الفعلية، يمكن أن يكون قائمة).

من API:

خيط آمن، تسلسل قابل للتغيير من الأحرف. مخزن مؤقت سلسلة يشبه السلسلة، ولكن يمكن تعديلها. في أي وقت، يحتوي على تسلسل معين من الأحرف، ولكن يمكن تغيير طول ومحتوى التسلسل من خلال مكالمات طريقة معينة.

يستخدم StringBuffer لإنشاء سلسلة واحدة من العديد من السلاسل، على سبيل المثال، عندما تريد إلحاق أجزاء من سلسلة في حلقة.

يجب عليك استخدام StringBuilder بدلا من StringBuffer عندما يكون لديك فقط مؤشر ترابط واحد يصل إلى StringBuffer، نظرا لأن StringBuilder غير متزامن وبالتالي بشكل أسرع.

لا يوجد حد أعلى لحجم السلسلة في Java بلغة، ولكن من المحتمل أن يكون لدى JVMS الحد الأعلى.

لقد وجدت إجابة الفائدة لمقارنة سلسلة الأداء مقابل StringBuffer بواسطة Reggie Hutchersoمصدر: http://www.javaworld.com/javaworld/jw-03-2000/jw-0324-javaperf.html.

توفر Java دروس StringBuffer و String، ويتم استخدام فئة السلسلة لمعالجة سلاسل الأحرف التي لا يمكن تغييرها. بتبديل، يتم قراءة كائنات سلسلة النوع فقط وغير قابلة للتغيير. يتم استخدام فئة StringBuffer لتمثيل الأحرف التي يمكن تعديلها.

فرق الأداء الهام بين هذين الطبقتين هو أن StringBuffer هو أسرع من السلسلة عند إجراء تستسمسا بسيطا. في رمز التلاعب السلسلة، يتم تسليم سلاسل الأحرف بشكل روتيني. استخدام فئة السلسلة، يتم تنفيذ التسوية عادة على النحو التالي:

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

إذا كنت تستخدم StringBuffer لأداء نفس التسليط، فستحتاج إلى رمز يشبه هذا:

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

عادة ما يفترض المطورون أن المثال الأول أعلاه أكثر كفاءة لأنهم يعتقدون أن المثال الثاني، والذي يستخدم طريقة إلحاق التسلسل، أكثر تكلفة من المثال الأول، والذي يستخدم المشغل + لتسلسل كائنتين سلسلة.

يبدو المشغل + بريئا، ولكن الكود الذي تم إنشاؤه ينتج عن بعض المفاجآت. باستخدام StringBuffer لسلسلة يمكن أن تنتج التعليمات البرمجية في الواقع أسرع بكثير من استخدام سلسلة. لاكتشاف لماذا هذا هو الحال، يجب علينا أن ندرس bytecode التي تم إنشاؤها من الأمثلة لدينا. يبدو bytecode للمثال باستخدام السلسلة مثل هذا:

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

يتم تنفيذ bytecode في المواقع 0 إلى 9 للسطر الأول من التعليمات البرمجية، أي:

 String str = new String("Stanford ");

بعد ذلك، يتم تنفيذ bytecode في الموقع 10 إلى 29 للحصول على التسلسل:

 str += "Lost!!";

الأمور تصبح مثيرة للاهتمام هنا. يقوم ByTecode الناتج عن التسلسل بإنشاء كائن StringBuffer، ثم يستدعي طريقة إلحاقه: يتم إنشاء كائن StringBuffer المؤقت في الموقع 10، ويتم استدعاء طريقة إلحاقها في الموقع 23. لأن فئة السلسلة غير قابلة للتغيير، يجب استخدام StringBuffer ل سلسلة.

بعد إجراء التسلسل على كائن StringBuffer، يجب تحويله إلى سلسلة. يتم ذلك مع المكالمة إلى طريقة ToString في الموقع 26. تقوم هذه الطريقة بإنشاء كائن سلسلة جديد من كائن StringBuffer المؤقت. إن إنشاء هذا الكائن المؤقت StringBuffer وتحويله اللاحق مرة أخرى في كائن سلسلة مكلفة للغاية.

باختصار، يؤدي سطرين من التعليمات البرمجية أعلاه إلى إنشاء ثلاث كائنات:

  1. كائن سلسلة في الموقع 0
  2. كائن StringBuffer في الموقع 10
  3. كائن سلسلة في الموقع 26

الآن، دعونا نلقي نظرة على bytecode الناتج عن المثال باستخدام 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

يتم تنفيذ bytecode في المواقع 0 إلى 9 للسطر الأول من التعليمات البرمجية:

 StringBuffer str = new StringBuffer("Stanford ");

ثم يتم تنفيذ ByTecode في الموقع 10 إلى 16 للحصول على التسلسل:

 str.append("Lost!!");

لاحظ أنه، كما هو الحال في المثال الأول، يستدعي هذا الرمز طريقة إلحاق كائن StringBuffer. على عكس المثال الأول، إلا أنه ليس هناك حاجة لإنشاء StringBuffer مؤقت ثم تحويله إلى كائن سلسلة. يقوم هذا الرمز بإنشاء كائن واحد فقط، StringBuffer، في الموقع 0.

في الختام، تتسلسل StringBuffer أسرع بكثير من سلسلة سلسلة. من الواضح أن Stringbuffers يجب أن تستخدم في هذا النوع من التشغيل عندما يكون ذلك ممكنا. إذا كانت وظيفة فئة السلسلة مرغوبة، ففكر في استخدام StringBuffer للحصول على سلسلات ثم إجراء تحويل واحد إلى سلسلة.

من خلال طباعة Hashcode من كائن السلسلة / StringBuffer بعد أن تثبت أي عملية إلحاقا أيضا، يتم إعادة إنشاء كائن السلسلة داخليا في كل مرة مع قيم جديدة بدلا من استخدام كائن السلسلة نفسه.

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());
    }

 }

}

الإخراج: يطبع قيمة الكائن جنبا إلى جنب مع 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

أ StringBuffer أو أخي أصغر وأسرع StringBuilder يفضل كلما كنت ستفعل الكثير من تسلسلات السلسلة في نكهة

string += newString;

أو مكافئ

string = string + newString;

لأن البناء أعلاه يخلق ضمنيا الجديد سلسلة في كل مرة سوف تكون أداء ضخمة وإسقاط. أ StringBuffer / StringBuilder تحت الأغطية أفضل مقارنة مع قابل للتوعية ديناميكيا List<Character>.

أ String هي صفيف شخصية ثابتة.

أ StringBuffer هي صفيف شخصية متغيرة. غالبا ما تم تحويلها مرة أخرى إلى String عند القيام بالتحوا

نظرا لأن كلاهما مجموعة، فإن الحد الأقصى للحجم كلاهما يساوي الحد الأقصى لحجم عدد صحيح، وهو 2 ^ 31-1 (انظر جافادوك, ، أيضا تحقق من جافادوك لكليهما String و StringBuffer). هذا بسبب .length حجة صفيف هي بدائية int. وبعد (يرى صفائف).

السلسلة غير قابلة للتغيير، مما يعني أنه عند إجراء عملية على سلسلة تقوم حقا بإنشاء سلسلة جديدة كاملة.

stringbuffer. هو قابل للتغيير، ويمكنك إلحاق ذلك وكذلك إعادة تعيين طولها إلى 0.

في الممارسة العملية، يبدو أن المحول البرمجي يستخدم StringBuffer أثناء سلسلة سلسلة لأسباب الأداء.

String is immutable. 

لماذا ا؟ يفحص هنا.

StringBuffer is not. It is thread safe. 

أسئلة أخرى مثل متى يمكن استخدام أي مفاهيم أخرى يمكن اعتبارها التالية هذه.

أتمنى أن يساعدك هذا.

بينما أفهم أن هذا ليس عاملا مختلفا كبيرا، فقد لاحظت اليوم أن StringBuffer (و Stringbuilder) يوفر بعض الأساليب المثيرة للاهتمام هذه السلسلة لا.

  • يعكس()
  • setcharat ()

الاختلافات هي

  1. فقط في سلسلة صف دراسي + المشغل مثقلة. يمكننا concat اثنين من كائن سلسلة باستخدام + المشغل، ولكن في حالة stringbuffer. لا يمكننا ذلك.
  2. سلسلة يتم تجاوز الفئة TOSTRING ()، يساوي ()، 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. سلسلة الطبقة كلاهما Serializable. إلى جانب قابلة للمقارنة, ، لكن stringbuffer. فقط Serializable..

    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. يمكننا إنشاء كائن سلسلة مع وبدون الجديد المشغل، ولكن لا يمكن إنشاء كائن StringBuffer فقط باستخدام الجديد المشغل أو العامل.

  5. سلسلة ثابتة ولكن stringbuffer هو قابلة للتغيير.
  6. متزامنة StringBuffer، في حين ليست السلسلة.
  7. StringBuffer هو وجود مدمج يعكس() الطريقة، ولكن سلسلة لا تملك ذلك.

الأداء الحكيم StringBuffer أفضل بكثير من السلسلة؛ لأنه كلما قمت بتطبيق التزلزال على كائن السلسلة، يتم إنشاء كائن سلسلة جديد على كل تسلسل.

القاعدة الرئيسية: سلسلة ثابتة (غير قابلة للتعديل) و 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

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top