مقدمة
بين مطوري Java ، غالبًا ما يكون شغل الموارد العالي للسلاسل موضوعًا ساخنًا.
دعنا نناقش بعمق لماذا تحتل موارد عالية.
في Java ، يكون كائن السلسلة غير قابل للتغيير ، مما يعني أنه بمجرد إنشائها ، لا يمكنك تغييره بعد الآن. لذلك عندما نقوم بصق السلاسل ، نقوم بإنشاء سلسلة جديدة ، ويتميز الجزء القديم بجامع القمامة.
إذا قمنا بمعالجة ملايين الأوتار ، فإننا ننشئ ملايين الأوتار الإضافية التي يتعين معالجتها بواسطة جامع القمامة.
في معظم البرامج التعليمية ، قد ترى أن استخدام علامات + لصياغة سلاسل سوف يولد سلاسل متعددة ، مما يؤدي إلى ضعف الأداء. يوصى باستخدام StringBuffer/StringBuilder لصياغة.
ولكن هل هذا هو الحال حقا؟
قامت هذه المقالة بالتجربة التالية في JDK8:
public static void main (string [] args) {string result = "" ؛ النتيجة += "بعض البيانات الأخرى" ؛ System.out.println (نتيجة) ؛ }فك الإلغاء من خلال Javap -C للحصول على:
الكود: 0: aload_0 // push 'this' to to the stack 1: invokespecial #1 // invoke complic classor // pop '' ref from the stack 4: return // return from constructor public static void main (java.lang.string []) ؛ الكود: 0: LDC #2 // تحميل ثابت #2 إلى المكدس 2: store_1 // إنشاء var المحلي من المكدس (pop #2) 3: جديد #3 // push new StringBuilder Ref on stack 6: dup // duplicate value pop of the stack 7: invokespecial #4 // invoke stringbuilder constructor // pop compan #5 // استدعاء طريقة stringbuilder.append () // pop obj Reference + Parmeter // push result (stringbuilder Ref) 14: ldc #6 // push "بعض البيانات الإضافية" على المكدس 16: invokevirtual #5 // invoke stringbuilder.append // pop twice ، push regup 19: invokevirtual #7 // invoke invoke ؛ 22: store_1 // إنشاء var المحلي من المكدس (pop #6) 23: getStatic #8 // نظام الدفع
يمكنك أن ترى أن برنامج التحويل البرمجي Java يحسن رمز Bytecode الذي تم إنشاؤه تلقائيًا ، يقوم تلقائيًا بإنشاء StringBuilder ، ويقوم بإجراء عمليات إلحاق.
نظرًا لأن السلسلة الفرعية للسلسلة النهائية معروفة بالفعل في وقت الترجمة ، فإن برنامج التحويل البرمجي Java سيؤدي التحسين أعلاه في هذه الحالة. يسمى هذا التحسين تحسين سلسلة متسلسل ثابت وتم تمكينه منذ JDK5.
هل هذا يعني أنه بعد JDK5 ، لم نعد بحاجة إلى إنشاء StringBuilder يدويًا ، ويمكننا تحقيق نفس الأداء من خلال علامة +؟
لنحاول خيوط الربط ديناميكيًا:
تشير سلاسل الربط الديناميكي إلى فرعية معروفة فقط في وقت التشغيل. على سبيل المثال ، إضافة سلسلة إلى حلقة:
public static void main (string [] args) {string result = "" ؛ لـ (int i = 0 ؛ i <10 ؛ i ++) {result+= "بعض بيانات أخرى" ؛ } system.out.println (result) ؛ }كما تم حلها:
الكود: 0: aload_0 // push 'this' to to the stack 1: invokespecial #1 // invoke complic classor // pop '' ref from the stack 4: return // return from constructor public static void main (java.lang.string []) ؛ الكود: 0: LDC #2 // تحميل ثابت #2 على المكدس 2: store_1 // إنشاء var المحلي من المكدس ، pop #2 3: iconst_0 // push value 0 على المكدس 4: ISTORE_2 // pop value وتخزينه في var 5: iload_2 // push local var on the stack 6: i2d // convement On int / . #6 // استدعاء StringBuilder Constructor // Pop Object Reference 21: aload_1 // push local var 1 (سلسلة فارغة) // إلى المكدس 22: invokevirtual #7 // invoke stringbuilder.append Ref + Param ، Push Result 30: InvokeVirtual #9 // invoke stringBuilder.ToString // pop Object Reference 33: store_1 // إنشاء var محلي من المكدس (pop) 34: iinc 2 ، 1 // string local ariable 2 by 1 37: goto 5 // انتقل إلى التعليمات في الرمز 5 40: getstatic #10 // spalue system. 44:
يمكنك أن ترى أن StringBuilder كان جديدًا في الرابعة عشرة من عمره ، ولكن في 37 عامًا ، Goto 5. خلال الحلقة ، لم يتم تحقيق التحسين ، وتم توليد البناء الجدد باستمرار.
لذلك الرمز أعلاه متشابه:
string result = "" ؛ for (int i = 0 ؛ i <10 ؛ i ++) {stringBuilder tmp = new StringBuilder () ؛ tmp.append (نتيجة) ؛ TMP.Append ("بعض البيانات الأخرى") ؛ النتيجة = tmp.toString () ؛} system.out.println (النتيجة) ؛يمكنك أن ترى أنه يتم إنشاء لاعبي StringBuilders الجدد باستمرار ، ومن خلال tostring ، لن يتم الرجوع إلى StringBuilder الأصلي ، كما القمامة ، وكذلك يزيد من تكلفة GC.
لذلك ، في الاستخدام الفعلي ، عندما لا يمكنك التمييز بين ما إذا كانت السلسلة ثابتة أو ديناميكية ، استخدم StringBuilder.
مرجع:
http://www.pellegrino.link/2015/08/22/string-concatenation-with-java-8.html
لخص
ما سبق هو المحتوى الكامل لهذه المقالة. آمل أن يكون لمحتوى هذه المقالة قيمة مرجعية معينة لدراسة أو عمل الجميع. إذا كان لديك أي أسئلة ، فيمكنك ترك رسالة للتواصل. شكرا لك على دعمك إلى wulin.com.