String vs StringBuffer vs StringBuilder

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

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

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

السلسلة في جافا

  1. تمثل فئة السلسلة سلاسل الأحرف ، يمكننا إنشاء كائن سلسلة بطريقتين.

    String str = "ABC";
    // أو
    String str = new String("ABC");
    
  2. السلسلة لا يمكن تغييرها في جافا. لذا فهي مناسبة للاستخدام في بيئة متعددة الخيوط. يمكننا مشاركتها عبر الوظائف لأنه لا يوجد مشكلة في تعارض البيانات.

  3. عند إنشاء سلسلة باستخدام علامات اقتباس مزدوجة، يبحث جهاز الجافا الافتراضي أولاً عن سلسلة بنفس القيمة في حافظة السلاسل. إذا تم العثور عليها، يعيد مرجع كائن السلسلة من حافظة السلاسل. وإلا، يقوم بإنشاء كائن السلسلة في حافظة السلاسل ويعيد المرجع. يوفر جهاز الجافا الافتراضي الكثير من الذاكرة عن طريق استخدام نفس السلسلة في خيوط مختلفة.

  4. إذا تم استخدام المشغل الجديد لإنشاء سلسلة، فإنها تنشأ في ذاكرة الكومة.

  5. تم تحميل المشغل + بشكل زائد للسلسلة. يمكننا استخدامه لدمج سلسلتين. على الرغم من استخدام StringBuffer داخليًا لأداء هذا الإجراء.

  6. تعديل سلسلة equals() وhashCode() الطرق. تكون سلسلتان متساويتان فقط إذا كان لديهما نفس تسلسل الأحرف. الطريقة equals() حساسة لحالة الأحرف. إذا كنت تبحث عن فحوصات غير حساسة لحالة الأحرف، يجب عليك استخدام طريقة equalsIgnoreCase().

  7. تستخدم السلسلة ترميز UTF-16 لمتسلسل الأحرف.

  8. السلسلة هي فئة نهائية. جميع الحقول هي نهائية باستثناء “private int hash”. يحتوي هذا الحقل على قيمة دالة hashCode(). تتم حساب قيمة hashcode فقط عندما يتم استدعاء طريقة hashCode() للمرة الأولى ومن ثم يتم تخزينها في هذا الحقل. علاوة على ذلك، يتم إنشاء الهاش باستخدام الحقول النهائية في فئة String مع بعض الحسابات. لذلك في كل مرة يتم استدعاء طريقة hashCode()، ستؤدي إلى نفس الناتج. بالنسبة للمتصل، يبدو وكأن الحسابات تحدث في كل مرة ولكن داخلياً يتم تخزينها في حقل الهاش.

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

نظرًا لأن السلسلة هي لا تتغير في Java، في كل مرة نقوم فيها بعملية تلاعب بالسلسلة مثل الدمج والتقسيم إلى أجزاء ، يتم إنشاء سلسلة جديدة ويتم التخلص من السلسة القديمة لإتاحة التخلص منها. هذه العمليات الثقيلة وتولد الكثير من النفايات في الذاكرة. لذلك ، قدمت Java فئتي StringBuffer و StringBuilder والتي يجب استخدامها لعمليات تلاعب السلسلة. StringBuffer و StringBuilder هما كائنات قابلة للتغيير في Java. توفران طرق append()، insert()، delete()، و substring() لعمليات تلاعب السلسلة.

StringBuffer مقابل StringBuilder

StringBuffer كانت الخيار الوحيد للتلاعب بالسلاسل حتى Java 1.4. لكن لديه عيب واحد وهو أن جميع الأساليب العامة له متزامنة. StringBuffer يوفر سلامة السلك لكن بتكلفة أداء. في معظم الحالات، لا نستخدم String في بيئة متعددة الخيوط. لذا قدمت Java 1.5 فئة جديدة تسمى StringBuilder، والتي تشبه StringBuffer باستثناء سلامة السلك والتزامن. StringBuffer لديه بعض الأساليب الإضافية مثل substring وlength وcapacity وtrimToSize، وما إلى ذلك. ومع ذلك، فإن هذه الأساليب غير مطلوبة حيث أن لديك كل هذه الوظائف متاحة في String أيضًا. لهذا السبب، لم يتم تنفيذ هذه الأساليب في فئة StringBuilder. تم تقديم StringBuffer في Java 1.0 بينما تم تقديم فئة StringBuilder في Java 1.5 بعد النظر إلى نقاط الضعف في StringBuffer. إذا كنت في بيئة ذات خيط واحد أو لا يهمك سلامة الخيط، يجب عليك استخدام StringBuilder. في حالة عكس ذلك، استخدم StringBuffer لعمليات آمنة للخيط.

أداء StringBuilder مقابل أداء StringBuffer

I am trying to check the effect on performance because of synchronization with a sample program that performs append() on StringBuffer and StringBuilder object for multiple times.

package com.journaldev.java;

import java.util.GregorianCalendar;

public class TestString {

	public static void main(String[] args) {
		System.gc();
		long start=new GregorianCalendar().getTimeInMillis();
		long startMemory=Runtime.getRuntime().freeMemory();
		StringBuffer sb = new StringBuffer();
		//StringBuilder sb = new StringBuilder();
		for(int i = 0; i<10000000; i++){
			sb.append(":").append(i);
		}
		long end=new GregorianCalendar().getTimeInMillis();
		long endMemory=Runtime.getRuntime().freeMemory();
		System.out.println("Time Taken:"+(end-start));
		System.out.println("Memory used:"+(startMemory-endMemory));
	}
}

I ran the same code for the StringBuffer object also to check the time and memory values. I have executed the code 5 times for each case and then calculated the average values.

Value of i StringBuffer (Time, Memory) StringBuilder (Time, Memory)
10,00,000 808, 149356704 633, 149356704
1,00,00,000 7448, 147783888 6179, 147783888

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

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

  1. السلسلة لا تتغير بينما StringBuffer و StringBuilder هي فئات قابلة للتغيير.
  2. StringBuffer متزامن وآمن للمواضيع بينما StringBuilder ليس كذلك. هذا هو السبب في أن StringBuilder أسرع من StringBuffer.
  3. مشغل اتصال السلاسل (+) يستخدم داخليًا فئة StringBuffer أو StringBuilder.
  4. بالنسبة لعمليات تحرير السلسلة في بيئة غير متعددة الخيوط ، يجب استخدام StringBuilder وإلا استخدام فئة StringBuffer.

هذا كل شيء لجولة سريعة حول الفرق بين السلسلة و StringBuffer و StringBuilder. StringBuilder أكثر ملاءمة من StringBuffer في معظم سيناريوهات البرمجة العامة. المراجع:

Source:
https://www.digitalocean.com/community/tutorials/string-vs-stringbuffer-vs-stringbuilder