StringBuilder Sınıfı
String Java'da değişmezdir (immutable): bir kez oluşturulan metin asla değişmez; "değiştirme" gibi görünen her işlem aslında yeni bir String üretir. Bu, güvenlik ve thread-güvenliği için harikadır ama bir metni parça…
StringBuilder Sınıfı
String Java'da değişmezdir (immutable): bir kez oluşturulan metin asla değişmez; "değiştirme"
gibi görünen her işlem aslında yeni bir String üretir. Bu, güvenlik ve thread-güvenliği için
harikadır ama bir metni parça parça inşa ederken ciddi bir performans sorununa dönüşür. İşte
StringBuilder tam da bunun için vardır: değiştirilebilir bir metin tamponu.
String neden yetmez?
String s = ""; for (int i = 0; i < 50000; i++) s += i; // her tur YENİ String kopyalar -> O(n^2)
Her +=, eski içeriği yeni bir String'e kopyalayıp yenisini ekler. N tur için bu, toplamda
O(n²) iştir — büyük N'de fark edilir biçimde yavaşlar ve bellek çöpü üretir.
StringBuilder: değiştirilebilir tampon
StringBuilder aynı, gerektiğinde büyüyen tampon üzerinde çalışır; kopyalama yapmaz:
StringBuilder sb = new StringBuilder(); for (int i = 0; i < 50000; i++) sb.append(i); // O(n) String sonuc = sb.toString();
Örnek 2 (./Ornek2.java) iki yaklaşımı ölçer; aradaki fark büyük N'de çarpıcıdır.
İncelik: Tek satırlık sabit birleştirmelerde (
a + b + c) derleyici zaten arka plandaStringBuilderkullanır; orada elle yazmana gerek yok. Asıl fark döngülerde ortaya çıkar — döngüde metin kuruyorsanStringBuilderkullan.
Temel metotlar
sb.append(x); // sona ekle (her tipi kabul eder: String, int, char, ...) sb.insert(pos, x); // konuma ekle sb.delete(from, to); // aralığı sil sb.deleteCharAt(i); sb.replace(from, to, s); // aralığı değiştir sb.reverse(); // ters çevir sb.setCharAt(i, c); sb.charAt(i); sb.length(); sb.toString(); // String'e çevir
Metotların çoğu StringBuilder'ın kendisini döndürür; bu yüzden zincirleme (method chaining)
yazılır: sb.append("[").append(x).append("]"). Örnek 1 (./Ornek1.java) tüm bu işlemleri ve
zincirlemeyi gösterir.
StringBuilder vs StringBuffer
İkisi aynı API'ye sahiptir; tek fark:
StringBuilder | StringBuffer | |
|---|---|---|
| Thread-safe | Hayır | Evet (metotlar synchronized) |
| Hız | Daha hızlı | Daha yavaş (kilit yükü) |
| Ne zaman | Varsayılan (tek thread) | Paylaşılan değiştirilebilir metin (nadir) |
Kural: Neredeyse her zaman StringBuilder kullan. StringBuffer'ı yalnızca aynı tampon birden
çok thread tarafından gerçekten paylaşılıyorsa düşün (çok nadir; genelde tasarımı değiştirmek daha
iyidir).
Modern alternatifler
String.join(",", liste): Bir koleksiyonu ayraçla birleştirmek için.Collectors.joining(",", "[", "]"): Stream'de birleştirme.String.format/ metin blokları: Biçimli/çok satırlı sabit metinler için.
Bunlar okunabilirlik sağlar; ama yoğun, koşullu, döngüsel metin inşasında hâlâ StringBuilder
en esnek ve en hızlı yoldur.
Özet
String'in değişmezliğinin döngüsel metin inşasında neden yavaş olduğunu; StringBuilder'ın
değiştirilebilir tamponla bunu nasıl çözdüğünü (Örnek 2); temel metotları ve zincirlemeyi (Örnek 1)
ve StringBuffer ayrımını öğrendik. "Döngüde metin kuruyorsan StringBuilder" altın kuraldır. Bu,
Class References bölümünün bu turdaki kısmını tamamlıyor.
▶ Kod Örnekleri(2)
Ornek1
çalıştırılabilir1// Ornek1: StringBuilder — değiştirilebilir metin: append/insert/delete/reverse/replace.
2// Çalıştırma: java Ornek1.java
3public class Ornek1 {
4
5 public static void main(String[] args) {
6 StringBuilder sb = new StringBuilder("Merhaba");
7
8 // append: sona ekleme (her tipi kabul eder)
9 sb.append(" ").append("Dünya").append('!').append(" ").append(2026);
10 System.out.println("append: " + sb);
11
12 // insert: belirli konuma ekleme
13 sb.insert(7, ", güzel");
14 System.out.println("insert: " + sb);
15
16 // delete / deleteCharAt
17 sb.delete(7, 14); // eklediğimiz ", güzel"i sil
18 System.out.println("delete: " + sb);
19
20 // replace
21 sb.replace(0, 7, "Selam");
22 System.out.println("replace: " + sb);
23
24 // reverse, length, charAt, setCharAt
25 StringBuilder ters = new StringBuilder("abcde").reverse();
26 System.out.println("reverse: " + ters);
27
28 // Method chaining (akıcı arayüz): her metot sb'yi döndürür
29 String sonuc = new StringBuilder()
30 .append("[").append("a").append(",").append("b").append("]")
31 .toString();
32 System.out.println("chaining: " + sonuc);
33
34 System.out.println("""
35
36 --- StringBuilder ---
37 String DEĞİŞMEZDİR (immutable): her "+" yeni bir String nesnesi yaratır.
38 StringBuilder DEĞİŞTİRİLEBİLİR: aynı tampon üzerinde ekler/siler/değiştirir -> verimli.
39 append/insert/delete/replace/reverse/setCharAt; toString() ile String'e çevrilir.
40 Metotlar sb'yi döndürdüğü için zincirleme (chaining) yazılır.""");
41 }
42}Ornek2
çalıştırılabilir1// Ornek2: Neden StringBuilder? — döngüde String birleştirme vs StringBuilder (ölçümle).
2// Çalıştırma: java Ornek2.java
3public class Ornek2 {
4
5 public static void main(String[] args) {
6 int N = 50_000;
7
8 // KÖTÜ: döngüde "+=" -> her adımda YENİ String kopyalanır (O(n^2) toplam).
9 long t1 = System.currentTimeMillis();
10 String s = "";
11 for (int i = 0; i < N; i++) s += i; // her seferinde yeni nesne!
12 long sure1 = System.currentTimeMillis() - t1;
13
14 // İYİ: StringBuilder -> aynı tampona ekler (O(n) toplam).
15 long t2 = System.currentTimeMillis();
16 StringBuilder sb = new StringBuilder();
17 for (int i = 0; i < N; i++) sb.append(i);
18 String sonuc = sb.toString();
19 long sure2 = System.currentTimeMillis() - t2;
20
21 System.out.printf("Döngüde birleştirme (%d):%n", N);
22 System.out.printf(" String += : ~%4d ms (uzunluk %d)%n", sure1, s.length());
23 System.out.printf(" StringBuilder: ~%4d ms (uzunluk %d)%n", sure2, sonuc.length());
24 System.out.println(" Kat fark ~ " + (sure2 == 0 ? ">>" : (sure1 / Math.max(1, sure2)) + "x"));
25
26 System.out.println("""
27
28 --- Neden döngüde StringBuilder? ---
29 String değişmez; "s += i" her turda eski içeriği + yeniyi YENİ bir String'e kopyalar.
30 N tur için bu O(n^2) iş demektir -> büyük N'de ciddi yavaşlık.
31 StringBuilder aynı genişleyen tampona ekler -> O(n). Döngüde metin kuruyorsan ŞART.
32 Not: TEK satırlık sabit birleştirmelerde (a + b + c) derleyici zaten StringBuilder kullanır;
33 orada elle StringBuilder gerekmez. Asıl fark DÖNGÜLERDEDİR.
34
35 StringBuffer: StringBuilder ile aynı API ama metotları senkronize (thread-safe).
36 Tek thread'de StringBuilder daha hızlıdır; StringBuffer'ı yalnızca paylaşılan
37 değiştirilebilir metin GERÇEKTEN gerektiğinde kullan (nadir).""");
38 }
39}