ما هو الفرق بين سلسلة و stringbuffer في جافا؟
-
19-09-2019 - |
سؤال
ما هو الفرق بين سلسلة و stringbuffer في جافا؟
هل هناك أقصى حجم لسلسلة؟
المحلول
String
يستخدم لمعالجة سلاسل الأحرف التي لا يمكن تغييرها (للقراءة فقط وغير قابلة للتطبيق).
StringBuffer
يستخدم لتمثيل الأحرف التي يمكن تعديلها.
أداء الحكمة، StringBuffer
هو أسرع عند أداء الملعات. هذا لأنه عندما تسقط String
, ، أنت تقوم بإنشاء كائن جديد (داخلي) في كل مرة String
غير ثابت.
تستطيع ايضا استخذام StringBuilder
وهو ما يشبه StringBuffer
باستثناء أنها غير متزامنة. الحد الأقصى للحجم لأي من هذه Integer.MAX_VALUE
(231 - 1 = 2،147،483،647) أو أقصى حجم الكومة مقسوما على 2 (انظر كم عدد الأحرف التي يمكن أن تكون سلسلة جافا؟). معلومات اكثر هنا.
نصائح أخرى
أ String
غير ثابت، أي عندما يتم إنشاؤه، لا يمكن تغييره أبدا.
أ StringBuffer
(أو ابن عمه غير المتزامن StringBuilder
) يستخدم عند الحاجة إلى بناء قطعة سلسلة من قطعة دون أداء النفقات العامة لبناء الكثير من القليل String
S على طول الطريق.
الحد الأقصى للطول كلاهما هو Integer.max_Value، لأنها يتم تخزينها داخليا كصفيفات، ومصفوفات Java لديها فقط int
لطول حقل الزائفة.
تحسين الأداء بين String
رمل StringBuffer
S للحصول على سلسلة متعددة مهم للغاية. إذا قمت بتشغيل رمز الاختبار التالي، فسترى الفرق. على جهاز الكمبيوتر المحمول القديم مع 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 وتحويله اللاحق مرة أخرى في كائن سلسلة مكلفة للغاية.
باختصار، يؤدي سطرين من التعليمات البرمجية أعلاه إلى إنشاء ثلاث كائنات:
- كائن سلسلة في الموقع 0
- كائن StringBuffer في الموقع 10
- كائن سلسلة في الموقع 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 أثناء سلسلة سلسلة لأسباب الأداء.
بينما أفهم أن هذا ليس عاملا مختلفا كبيرا، فقد لاحظت اليوم أن StringBuffer (و Stringbuilder) يوفر بعض الأساليب المثيرة للاهتمام هذه السلسلة لا.
- يعكس()
- setcharat ()
الاختلافات هي
- فقط في سلسلة صف دراسي + المشغل مثقلة. يمكننا concat اثنين من كائن سلسلة باستخدام + المشغل، ولكن في حالة stringbuffer. لا يمكننا ذلك.
سلسلة يتم تجاوز الفئة 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
سلسلة الطبقة كلاهما 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
يمكننا إنشاء كائن سلسلة مع وبدون الجديد المشغل، ولكن لا يمكن إنشاء كائن StringBuffer فقط باستخدام الجديد المشغل أو العامل.
- سلسلة ثابتة ولكن stringbuffer هو قابلة للتغيير.
- متزامنة StringBuffer، في حين ليست السلسلة.
- 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