String varken neden StringBuilder?


83

StringBuilderJava'nın zaten Stringeklemeye izin veren çok güçlü bir sınıfa sahip olması nedeniyle ilk kez karşılaştım ve şaşırdım .

Neden ikinci Stringsınıf?

Daha fazla bilgiyi nereden öğrenebilirim StringBuilder?



Bunun bir keresinde benim için bir röportaj sorusu olarak ortaya çıktığını belirtmek istedim. Büyük bir String'i ne doldurmak istediğimi sordular .....
preOtep

Yanıtlar:


172

Stringeklemeye izin vermiyor. A'da çalıştırdığınız her yöntem Stringyeni bir nesne oluşturur ve onu döndürür. Bunun nedeni Stringdeğişmez olmasıdır - iç durumunu değiştiremez.

Öte yandan StringBuilderdeğişebilir. Onu çağırdığınızda append(..), yeni bir dize nesnesi oluşturmak yerine dahili karakter dizisini değiştirir.

Bu nedenle şunlara sahip olmak daha etkilidir:

StringBuilder sb = new StringBuilder();
for (int i = 0; i < 500; i ++) {
    sb.append(i);
}

yerine str += i, 500 yeni dize nesnesi oluşturacaktır.

Örnekte bir döngü kullandığıma dikkat edin. Helios'un yorumlarda belirttiği gibi, derleyici benzer ifadeleri otomatik String d = a + b + colarak şöyle bir şeye çevirir:

String d = new StringBuilder(a).append(b).append(c).toString();

Ayrıca StringBufferek olarak olduğunu unutmayın StringBuilder. Aradaki fark, eskisinin senkronize yöntemlere sahip olmasıdır. Yerel değişken olarak kullanırsanız StringBuilder,. Birden fazla iş parçacığı tarafından erişilmesi mümkünse, kullanın StringBuffer(bu daha nadirdir)


26
+1. Ekleyebilirsiniz: "dolayısıyla StrungBuilder performans arar" ve "Java derleyicileri, nesne oluşturma performansından kaçınmak için A + B + C gibi ifadeleri yeni StringBuilder (A) .append (B) .append (C) .toString () ile değiştirir. penaltılar ":)
helios

ve hepinize çok teşekkür ederim. Hepiniz +
1'leri

süper 'değişmez' nesnelerin hatırlanması gibi.
Gary Tsui

Harika tepkiler. Ancak özlediğim şey, derleyicinin çoğu zaman Stringbuilder'ı ne zaman kullanacağımızı çözemememizin nedeni , döngüleri de dahil olmak üzere, böylece onu bir geliştirici olarak düşünmenize gerek kalmaz. :)
worldsayshi

İyi cevap . Bu satırları eklemek istiyorum: String, diziyi tutan dizi olarak (yani char [] değeri) son olarak bildirilir, ancak StringBuilder durumunda dizeyi tutan dizi (yani char [] değeri) son değildir. Stringbuilder durumunda dizeyi tutan dizide değişiklikler yapabilirsiniz
Deen John

61

İşte neden olduğuna dair somut bir örnek -

int total = 50000;
String s = ""; 
for (int i = 0; i < total; i++) { s += String.valueOf(i); } 
// 4828ms

StringBuilder sb = new StringBuilder(); 
for (int i = 0; i < total; i++) { sb.append(String.valueOf(i)); } 
// 4ms

Gördüğünüz gibi performanstaki fark önemli.


Ps. Bunu Macbook Pro Çift çekirdeğimde çalıştırdım.
Amir Raminfar

25
Bu , String varken neden StringBuilder'ı açıklıyor ? Bu, StringBuilder'ın neden bu kadar hızlı olduğunu açıklamıyor . ama bu Soru değil. Yani bu geçerli bir cevap.
Kerem Baydoğan

2
@krmby - Kabul edildi. Nedenini cevaplamak gerçekten başka bir soru içindir.
Amir Raminfar

12
Bence karşılaştırmayı adil yapmak için, s = sb.ToString();en azından her iki örnekte de aynı şeyi yaptın (sonuç a string).
Scott Whitlock

19

String sınıfı değişmezken StringBuilder değiştirilebilir.

String s = "Hello";
s = s + "World";

Yukarıdaki kod iki nesne oluşturacak çünkü String değişmez

StringBuilder sb = new StringBuilder("Hello");
sb.append("World");

Yukarıdaki kod yalnızca bir nesne oluşturacaktır çünkü StringBuilder değişmez değildir.

Ders: String'i manipüle etme / güncelleme / ekleme ihtiyacı olduğunda, birçok kez StringBuilder, String'e kıyasla verimli olduğu için StringBuilder'a gidin.


8

StringBuilder, dizeler oluşturmak içindir. Özellikle, onları çok performanslı bir şekilde inşa etmek. String sınıfı birçok şey için iyidir, ancak aslında daha küçük dizgi parçalarından yeni bir dizi oluştururken gerçekten korkunç bir performansa sahiptir çünkü her yeni dizi tamamen yeni, yeniden tahsis edilmiş bir dizedir. ( Değişmezdir ) StringBuilder aynı sırayı yerinde tutar ve onu değiştirir ( değiştirilebilir ).


5

StringBuilder sınıfı değiştirilebilir ve String'den farklı olarak, daha fazla String nesnesi oluşturmanıza gerek kalmadan dizenin içeriğini değiştirmenize olanak tanır; bu, bir dizeyi yoğun bir şekilde değiştirirken bir performans kazanımı olabilir. Ayrıca StringBuilder için StringBuffer adında bir muadili vardır ve bu da senkronize edilir, bu nedenle çok iş parçacıklı ortamlar için idealdir.

String ile ilgili en büyük sorun, onunla yaptığınız herhangi bir işlemin her zaman yeni bir nesne döndürmesidir, örneğin:

String s1 = "something";
String s2 = "else";
String s3 = s1 + s2; // this is creating a new object.

4

StringBuilder, daha büyük dizelerle uğraşırken iyidir. Performansı artırmanıza yardımcı olur.

İşte yararlı bulduğum bir makale .

Hızlı bir Google araması size yardımcı olabilirdi. Şimdi sizin için bir google araması yapması için 7 farklı kişiyi işe aldınız. :)


Hepimiz burada ücretsiz işler yapmıyor muyuz?
CA Arefe

4

Kesin olmak gerekirse, StringBuilder tüm dizeleri eklerken O (N), String'ler ise O (N ^ 2). Kaynak kodunu kontrol ederek, bu dahili olarak değiştirilebilir bir karakter dizisi tutularak elde edilir. StringBuilder , gerekli belleği ikiye katlama pahasına ammortized O (N ^ 2) performansı elde etmek için dizi uzunluğu çoğaltma tekniğini kullanır . Bunu çözmek için sonunda trimToSize'ı çağırabilirsiniz, ancak genellikle StringBuilder nesneleri yalnızca geçici olarak kullanılır. Nihai dize boyutunda iyi bir başlangıç ​​tahmini sağlayarak performansı daha da artırabilirsiniz.


3

Verimlilik.

Dizeleri her birleştirdiğinizde, yeni bir dize oluşturulacaktır. Örneğin:

String out = "a" + "b" + "c";

Bu yeni, geçici bir dize oluşturur, "a" ve "b" yi "ab" ile sonuçlanacak şekilde kopyalar. Sonra başka bir yeni, geçici dize oluşturur, "ab" ve "c" yi kopyalayarak "abc" ile sonuçlanır. Bu sonuç daha sonra atanır out.

Sonuç, bir Schlemiel the Painter'ın O (n²) (ikinci dereceden) zaman karmaşıklığı algoritmasıdır .

StringBuilderDiğer yandan, çıktı dizesini gerektiği gibi yeniden boyutlandırarak yerinde dizeler eklemenize olanak tanır.


Birçok JVM uygulaması, örneğinizi bir StringBuilder'da derler ve ardından son sonucu String'e dönüştürür. Böyle bir durumda, tekrarlanan Dize tahsisleri ile birleştirilmeyecektir.
scottb

1

Java'da String, StringBuffer ve StringBuilder vardır:

  • Dize: Değişmez

  • StringBuffer: Değişken ve ThreadSafe

  • StringBuilder: Değişken ama ThreadSafe Değil, Java 1.5 ile birlikte sunuldu

Dize, örneğin:

public class T1 {

    public static void main(String[] args){

        String s = "Hello";

        for (int i=0;i<10;i++) {

            s = s+"a";
            System.out.println(s);
        }
    }
}

}

output: Sadece 1 String yerine 10 Farklı String oluşturulacaktır.

Helloa
Helloaa
Helloaaa
Helloaaaa
Helloaaaaa
Helloaaaaaa
Helloaaaaaaa
Helloaaaaaaaa 
Helloaaaaaaaaa 
Helloaaaaaaaaaa

StringBuilder örneğin: Yalnızca 1 StringBuilder nesnesi oluşturulacaktır.

public class T1 {

    public static void main(String[] args){

        StringBuilder s = new StringBuilder("Hello");

        for (int i=0;i<10;i++) {    
            s.append("a");
            System.out.println(s);
        }
    }
}
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.