1. Sətirin dəyişməzliyi: dost, yoxsa düşmən?
Java-da String sinfi — dəyişməzdir (immutable). Bu o deməkdir ki, yaradıldıqdan sonra sətiri dəyişmək olmaz. Hər dəfə sətiri “dəyişdirdiyiniz”, məsələn, ona + və ya concat() vasitəsilə nəsə əlavə etdiyiniz zaman, əslində yeni obyekt yaradılır, köhnəsi isə tarixin (və yaddaşın) zibilxanasına göndərilir.
Nümunə:
String s = "Hello";
s = s + " world!";
System.out.println(s); // Hello world!
Elə görünür ki, s sətiri dəyişib, amma əslində yeni "Hello world!" sətiri yaradıldı, köhnə "Hello" isə garbage collector onu silənədək yaddaşda qalır. Belə əməliyyatlar çox olanda — məsələn, dövr daxilində — proqram yavaşıyır və artıq yaddaş istifadə edir.
Təsəvvür edin ki, kublardan bir qüllə qurursunuz və hər dəfə yeni kub əlavə etmək istəyəndə bütün qülləni yenidən qurmalı olursunuz. O qədər də səmərəli deyil, düzdür? Tez-tez dəyişikliklər zamanı Java-da adi String məhz belə işləyir.
2. StringBuilder: sətirlər üçün sürətli “qurucu”
StringBuilder sinfi (java.lang paketi, import etməyə ehtiyac yoxdur) — sətirləri effektiv şəkildə toplamaq və dəyişmək üçün xüsusi alətdir. O, dəyişəndir (mutable): hər əməliyyatda yeni obyekt yaratmadan simvol və alt sətirləri əlavə etmək, silmək, daxil etmək mümkündür.
Analoqiya:
Əgər String beton plitədirsə, StringBuilder LEGO konstrukturudur: hissələri istədiyiniz qədər əlavə edib çıxarırsınız, hamısını yenidən sökmək lazım olmur.
StringBuilder necə yaradılır
StringBuilder sb = new StringBuilder(); // boş
StringBuilder sb2 = new StringBuilder("Başlanğıc dəyər");
Əsas metodlar
| Metod | Təsvir | İstifadə nümunəsi |
|---|---|---|
|
Sona sətir, rəqəm, simvol və s. əlavə etmək | |
|
Göstərilən mövqeyə dəyər daxil etmək | |
|
start mövqeyindən (daxil olmaqla) end mövqeyinədək (daxil deyil) simvolları silmək | |
|
Sətirin bir hissəsini başqa məzmunla əvəz etmək | |
|
Sətiri tərsinə çevirmək | |
|
Adi sətirə çevirmək | |
|
Sətiri verilən uzunluğa qısaltmaq və ya uzatmaq | |
İstifadə nümunəsi
StringBuilder sb = new StringBuilder();
sb.append("Salam, ");
sb.append("dünya!");
System.out.println(sb); // Salam, dünya!
sb.insert(7, "Java "); // "Salam, " sözündən sonra "Java " əlavə edək
System.out.println(sb); // Salam, Java dünya!
sb.replace(8, 12, "başqa"); // "Java"-nı "başqa" ilə əvəz edək
System.out.println(sb); // Salam, başqa dünya!
sb.reverse();
System.out.println(sb); // !aynüd aqşab ,malaS
3. StringBuffer: çoxaxınlı mühit üçün təhlükəsiz “böyük qardaş”
Fərq nədədir: StringBuilder və StringBuffer?
- StringBuilder — sürətlidir, lakin axın-təhlükəsiz deyil (sinxronlaşdırılmamışdır).
- StringBuffer — bir qədər yavaşdır, lakin axın-təhlükəsizdir (sinxronlaşdırılmışdır).
Əgər tətbiqiniz bir axında işləyirsə — StringBuilder istifadə edin (daha sürətlidir). Eyni sətiri bir neçə axın dəyişə bilirsə — StringBuffer istifadə edin.
4. String əvəzinə StringBuilder-i nə vaxt istifadə etməli?
Ssenarilər
- Dövr və ya böyük mətnlərin yığılması zamanı sətirin tez-tez dəyişdirilməsi (əlavə etmə, silmə, daxil etmə).
- Massivdən/siyahıdan sətir yığmaq (CSV, HTML, hesabatlar və s.).
- Çoxsaylı sətir əməliyyatları olan mətnin parslanması və emalı.
Nümunə: massivdən sətir yığmaq
Pis üsul (String və + vasitəsilə):
String[] names = {"İvan", "Pyotr", "Mariya"};
String result = "";
for (int i = 0; i < names.length; i++)
{
result += names[i];
if (i < names.length - 1)
{
result += ", ";
}
}
System.out.println(result);
Yaxşı üsul (StringBuilder vasitəsilə):
String[] names = {"İvan", "Pyotr", "Mariya"};
StringBuilder sb = new StringBuilder();
for (int i = 0; i < names.length; i++)
{
sb.append(names[i]);
if (i < names.length - 1)
{
sb.append(", ");
}
}
System.out.println(sb.toString());
Fərq: birinci halda hər addımda yeni sətir yaradılır, ikinci halda isə eyni StringBuilder obyektini böyüdürük.
5. Məhsuldarlıq müqayisəsi: String vs StringBuilder
// String vasitəsilə
long t1 = System.currentTimeMillis();
String s = "";
for (int i = 0; i < 10000; i++)
{
s += i + " ";
}
long t2 = System.currentTimeMillis();
System.out.println("String: " + (t2 - t1) + " ms");
// StringBuilder vasitəsilə
t1 = System.currentTimeMillis();
StringBuilder sb = new StringBuilder();
for (int i = 0; i < 10000; i++)
{
sb.append(i).append(" ");
}
s = sb.toString();
t2 = System.currentTimeMillis();
System.out.println("StringBuilder: " + (t2 - t1) + " ms");
Nəticə: əksər hallarda StringBuilder çoxsaylı birləşdirmələrdə dəfələrlə daha sürətli işləyir.
6. Faydalı nüanslar
String metodlarından istifadə etmək olar?
StringBuilder-in öz metodları var. Sətir əldə etmək üçün toString() çağırın.
StringBuilder sb = new StringBuilder("Hello");
String s = sb.toString(); // indi s — adi sətirdir
StringBuilder-i equals ilə müqayisə etmək olarmı?
Diqqət: sb1.equals(sb2) istinadları müqayisə edir, məzmunu yox. Belə müqayisə edin:
if (sb1.toString().equals(sb2.toString()))
{
// məzmun eynidir
}
StringBuilder-i System.out.println-ə ötürmək olar?
Bəli. System.out.println avtomatik olaraq toString() çağıracaq.
Simvolları indeks üzrə oxumaq olarmı?
Bəli, adi sətirdə olduğu kimi charAt(int index) istifadə edin.
7. StringBuilder və StringBuffer ilə işləyərkən tipik səhvlər
Xəta №1: iki StringBuilder-i equals və ya == operatoru ilə müqayisə etmək. Bu yoxlamalar istinadları müqayisə edir, məzmunu yox. toString() və sətir müqayisəsindən istifadə edin.
Xəta №2: toString()-i String gözlənilən yerdə (metoddan qaytararkən, jurnallaşdırma, API-yə ötürmə) çağırmağı unutmaq.
Xəta №3: bir-iki sadə birləşdirmə üçün StringBuilder tətbiq etmək. "Hello, " + name yazılışı oxunaqlıdır və kifayət qədər səmərəlidir.
Xəta №4: dövrdə String-ləri + ilə birləşdirmək. Bu vaxt və yaddaş baxımından qeyri-səmərəlidir — StringBuilder istifadə edin.
Xəta №5: ehtiyac olmadan StringBuffer ilə StringBuilder-i qarışdırmaq. Bir neçə axından eyni obyektin dəyişdirilməsi yoxdursa — StringBuilder seçin.
Xəta №6: StringBuilder-in məzmununu setLength() metodu ilə düşünmədən kəsmək. Yeni uzunluğun düzgünlüyünü yoxlayın, ondan sonrakı məlumatlar itiriləcək.
GO TO FULL VERSION