JavaRush /مدونة جافا /Random-AR /مقدمة إلى String وStringBuffer وStringBuilder في Java

مقدمة إلى String وStringBuffer وStringBuilder في Java

نشرت في المجموعة
هناك ثلاث فئات في Java للعمل مع البيانات النصية: String و StringBuffer و StringBuilder . يواجه كل مطور أول مطور في بداية تعلم اللغة. ماذا عن الاثنين المتبقيين؟ ما هي الاختلافات بينهما، ومتى يكون من الأفضل استخدام فئة أو أخرى؟ بشكل عام، الفرق بينهما صغير، ولكن من الأفضل أن نفهم كل شيء في الممارسة العملية :) مقدمة إلى String وStringBuffer وStringBuilder في Java - 1

فئة السلسلة

تمثل هذه الفئة سلسلة من الأحرف. كافة القيم الحرفية للسلسلة المحددة في البرامج، مثل "هذه سلسلة" هي مثيلات لفئة السلسلة. تحتوي السلسلة على ميزتين أساسيتين:
  • هذه فئة غير قابلة للتغيير
  • هذا هو الفصل النهائي
بشكل عام، لا يمكن أن تحتوي فئة السلسلة على أطفال ( final) ولا يمكن تعديل مثيلات الفئة بعد الإنشاء ( immutable). وهذا يمنح فئة String العديد من المزايا المهمة:
  1. بسبب عدم القابلية للتغيير، يتم تخزين رمز التجزئة لمثيل فئة السلسلة مؤقتًا. لا يلزم تقييمه في كل مرة لأن قيم حقول الكائن لن تتغير أبدًا بعد إنشائه. وهذا يعطي أداءً عاليًا عند استخدام هذه الفئة كمفتاح لـ HashMap.

  2. يمكن استخدام فئة السلسلة في بيئة متعددة الخيوط دون الحاجة إلى مزامنة إضافية.

  3. ميزة أخرى لفئة String هي أنها تزيد من تحميل +عامل التشغيل " " في Java. ولذلك، فإن تسلسل (إضافة) السلاسل أمر بسيط للغاية:

public static void main(String[] args) {
    String command = "Follow" + " " + "the" + " " + "white" + " " + "rabbit";
    System.out.println(command); // Follow the white rabbit
}
تحت الغطاء، يتم تنفيذ تسلسل السلسلة بواسطة فئة StringBuilder أو StringBuffer (حسب تقدير المترجم) وطريقة append(سنتحدث عن هذه الفئات لاحقًا). إذا أضفنا مثيلات فئة السلسلة مع مثيلات الفئات الأخرى، فسيتم تقليل الأخير إلى تمثيل سلسلة:
public static void main(String[] args) {
    Boolean b = Boolean.TRUE;
    String result = "b is " + b;
    System.out.println(result); //b is true
}
هذه خاصية أخرى مثيرة للاهتمام لفئة السلسلة: يمكن تحويل كائنات أي فئة إلى تمثيل سلسلة باستخدام الطريقة toString()المحددة في الفئة Objectورثتها جميع الفئات الأخرى. غالبًا ما يتم استدعاء الأسلوب toString() على الكائن ضمنيًا. على سبيل المثال، عندما نعرض شيئًا ما على الشاشة أو نضيف سلسلة إلى كائن من فئة أخرى. تحتوي فئة String على ميزة أخرى. يتم تخزين جميع القيم الحرفية للسلسلة المحددة في كود Java، مثل "asdf"، مؤقتًا في وقت الترجمة وإضافتها إلى ما يسمى بتجمع السلاسل. إذا قمنا بتشغيل الكود التالي:
String a = "Wake up, Neo";
String b = "Wake up, Neo";

System.out.println(a == b);
سنرى أن هذا صحيح في وحدة التحكم لأن المتغيرات ستشير aفعليًا bإلى نفس مثيل فئة السلسلة التي تمت إضافتها إلى تجمع السلسلة في وقت الترجمة. أي أنه لا يتم إنشاء مثيلات مختلفة للفئة بنفس القيمة، ويتم حفظ الذاكرة.

عيوب:

ليس من الصعب تخمين أن فئة السلسلة مطلوبة بشكل أساسي للعمل مع السلاسل. ولكن في بعض الحالات، يمكن أن تتحول الميزات المذكورة أعلاه لفئة السلسلة من المزايا إلى العيوب. بمجرد إنشاء السلاسل النصية في كود Java، غالبًا ما يتم تنفيذ العديد من العمليات عليها:
  • تحويل السلاسل إلى سجلات مختلفة؛
  • استخراج السلسلة الفرعية
  • سلسلة؛
  • إلخ.
دعونا نلقي نظرة على هذا الرمز:
public static void main(String[] args) {

    String s = " Wake up, Neo! ";
    s = s.toUpperCase();
    s = s.trim();

    System.out.println("\"" + s + "\"");
}
للوهلة الأولى، يبدو أننا قمنا للتو بترجمة السطر "استيقظ يا نيو!" إلى أحرف كبيرة، قم بإزالة المسافات الزائدة من هذه السلسلة ولفها بين علامتي اقتباس. في الواقع، نظرًا لعدم قابلية تغيير فئة السلسلة، نتيجة لكل عملية، يتم إنشاء مثيلات سلسلة جديدة ويتم التخلص من مثيلات السلسلة القديمة، مما يؤدي إلى إنشاء كمية كبيرة من البيانات المهملة. كيف تتجنب هدر الذاكرة؟

فئة StringBuffer

للتعامل مع إنشاء القمامة المؤقتة بسبب التعديلات على كائن سلسلة، يمكنك استخدام فئة StringBuffer. هذا mutableصنف، أي. قابل للتغيير. يمكن أن يحتوي كائن فئة StringBuffer على مجموعة محددة من الأحرف، والتي يمكن تغيير طولها وقيمتها عن طريق استدعاء طرق معينة. دعونا نرى كيف يعمل هذا الفصل. لإنشاء كائن جديد، استخدم أحد منشئيه، على سبيل المثال:
  • StringBuffer() - سيُنشئ كائنًا فارغًا (بدون أحرف).
  • StringBuffer(String str) - سيقوم بإنشاء كائن بناءً على متغير str (يحتوي على جميع أحرف str في نفس التسلسل)
يمارس:
StringBuffer sb = new StringBuffer();
StringBuffer sb2 = new StringBuffer("Not empty");
يتم تسلسل السلاسل عبر StringBuffer في Java باستخدام ملحق append. بشكل عام، يتم تحميل الطريقة appendالموجودة في فئة StringBuffer بشكل زائد بحيث يمكنها قبول أي نوع بيانات تقريبًا:
public static void main(String[] args) {
    StringBuffer sb = new StringBuffer();

    sb.append(new Integer(2));
    sb.append("; ");
    sb.append(false);
    sb.append("; ");
    sb.append(Arrays.asList(1,2,3));
    sb.append("; ");

    System.out.println(sb); // 2; false; [1, 2, 3];
}
تقوم الطريقة appendبإرجاع الكائن الذي تم استدعاؤها عليه (مثل العديد من الطرق الأخرى)، مما يسمح باستدعائها في "سلسلة". يمكن كتابة المثال أعلاه على النحو التالي:
public static void main(String[] args) {
    StringBuffer sb = new StringBuffer();

    sb.append(new Integer(2))
            .append("; ")
            .append(false)
            .append("; ")
            .append(Arrays.asList(1,2,3))
            .append("; ");

    System.out.println(sb); // 2; false; [1, 2, 3];
}
تحتوي فئة StringBuffer على عدد من الطرق للتعامل مع السلاسل النصية. دعونا ندرج أهمها:
  • delete(int start, int end)- يحذف سلسلة فرعية من الأحرف تبدأ من الموضع startوتنتهيend
  • deleteCharAt(int index)- يحذف الحرف الموجود في الموضعindex
  • insert(int offset, String str)— يُدرج سطرًا strفي الموضع offset. يتم أيضًا تحميل الطريقة insertبشكل زائد ويمكن أن تأخذ وسائط مختلفة
  • replace(int start, int end, String str)- سيتم استبدال جميع الأحرف من موضع startإلى endآخرstr
  • reverse()- يعكس ترتيب جميع الأحرف
  • substring(int start)- سيُرجع سلسلة فرعية تبدأ من الموضع start
  • substring(int start, int end)- سيُرجع سلسلة فرعية تبدأ من موضع startإلى آخرend
توجد قائمة كاملة بالأساليب والمنشئات في الوثائق الرسمية . كيف تعمل الطرق المذكورة أعلاه؟ دعونا نرى في الممارسة العملية:
public static void main(String[] args) {
     String numbers = "0123456789";

     StringBuffer sb = new StringBuffer(numbers);

     System.out.println(sb.substring(3)); // 3456789
     System.out.println(sb.substring(4, 8)); // 4567
     System.out.println(sb.replace(3, 5, "ABCDE")); // 012ABCDE56789

     sb = new StringBuffer(numbers);
     System.out.println(sb.reverse()); // 9876543210
     sb.reverse(); // Return the original order

     sb = new StringBuffer(numbers);
     System.out.println(sb.delete(5, 9)); // 012349
     System.out.println(sb.deleteCharAt(1)); // 02349
     System.out.println(sb.insert(1, "One")); // 0One2349
    }

مزايا:

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

  2. StringBuffer هي فئة آمنة لمؤشر الترابط. تتم مزامنة أساليبها ويمكن استخدام المثيلات بواسطة سلاسل رسائل متعددة في وقت واحد.

عيوب:

من ناحية، تعتبر سلامة الخيط ميزة للفئة، ومن ناحية أخرى، فهي عيب. الأساليب المتزامنة أبطأ من الأساليب غير المتزامنة. هذا هو المكان الذي يلعب فيه StringBuilder. دعونا نتعرف على نوع فئة Java - StringBuilder، وما هي الأساليب التي تستخدمها وما هي ميزاتها.

فئة StringBuilder

StringBuilder في Java هي فئة تمثل سلسلة من الأحرف. إنه مشابه جدًا لـ StringBuffer في كل شيء باستثناء أمان الخيط. يوفر StringBuilder واجهة برمجة تطبيقات مشابهة لواجهة StringBuffer. دعونا نوضح ذلك باستخدام مثال مألوف بالفعل، مع استبدال إعلان المتغيرات من StringBufer إلى StringBuilder:
public static void main(String[] args) {
    String numbers = "0123456789";

    StringBuilder sb = new StringBuilder(numbers);

    System.out.println(sb.substring(3)); //3456789
    System.out.println(sb.substring(4, 8)); //4567
    System.out.println(sb.replace(3, 5, "ABCDE")); //012ABCDE56789

    sb = new StringBuilder(numbers);
    System.out.println(sb.reverse()); //9876543210
    sb.reverse(); // Return the original order

    sb = new StringBuilder(numbers);
    System.out.println(sb.delete(5, 9)); //012349
    System.out.println(sb.deleteCharAt(1)); //02349
    System.out.println(sb.insert(1, "One")); //0One2349
}
والفرق الوحيد هو أن StringBuffer آمن لمؤشر الترابط وجميع أساليبه متزامنة، في حين أن StringBuilder ليس كذلك. هذه هي الميزة الوحيدة. يعد StringBuilder في Java أسرع من StringBuffer بسبب عدم مزامنة الأساليب. لذلك، في معظم الحالات، باستثناء بيئة متعددة الخيوط، من الأفضل استخدام StringBuilder لبرنامج Java. نلخص كل شيء في جدول مقارن للفئات الثلاث:

سلسلة مقابل StringBuffer مقابل StringBuilder

خيط StringBuffer StringBuilder
قابلية التغيير Immutable(لا) mutable(نعم) mutable(نعم)
القابلية للتوسعة final(لا) final(لا) final(لا)
سلامة الخيط نعم، بسبب الثبات نعم، بسبب المزامنة لا
متى يجب استخدام عند العمل مع سلاسل نادرًا ما يتم تعديلها عند العمل مع السلاسل التي سيتم تعديلها بشكل متكرر في بيئة متعددة الخيوط عند العمل مع السلاسل التي سيتم تعديلها بشكل متكرر في بيئة ذات ترابط واحد
يمكنك دراسة هذا الموضوع بمزيد من التفصيل في المستوى الثاني من مهمة Java Multithreading في دورة JavaRush:
تعليقات
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION