Yanıtlar:
Değişebilirlik Farkı:
String
ise değişmez onların değerlerini değiştirmeye çalışırsanız, başka bir nesne ise, oluşturulan alır, StringBuffer
ve StringBuilder
vardır değişken onların değerlerini değiştirebilir böylece.
İplik Güvenliği Farkı:
Arasındaki fark StringBuffer
ve StringBuilder
olmasıdır StringBuffer
parçacığı güvenlidir. Bu nedenle, uygulamanın yalnızca tek bir iş parçacığında çalıştırılması gerektiğinde kullanmak daha iyidir StringBuilder
. StringBuilder
daha verimlidir StringBuffer
.
durumlar:
String
Dizeniz değişmeyecekse, nesne değiştirilemediğinden bir String sınıfı kullanın .StringBuilder
yeterince iyidir.StringBuffer
çünkü StringBuffer
zaman uyumludur.Strings
değeri değiştirdiğimizde başka bir nesne yaratılır. Eski nesne referansı, tarafından GC
toplanan çöpün toplanabilmesi için mi yoksa çöp toplanabiliyor mu?
String
ile StringBuilder
?
String
Değişmez bir yapı uygun olduğunda kullanırsınız ; a'dan yeni bir karakter dizisi elde etmek String
, CPU zamanı veya bellekte kabul edilemez bir performans cezası taşıyabilir (veriler kopyalanmadığı için alt dizeleri elde etmek CPU verimlidir, ancak bu potansiyel olarak çok daha büyük miktarda veri tahsis edilebileceği anlamına gelir).StringBuilder
Eğer bir değişken karakter dizisini yaratmak için genellikle bir arada birkaç karakter dizilerini bitiştirmek gerektiğinde.StringBuffer
aynı koşullarda kullanırsınız StringBuilder
, ancak temel dizede yapılan değişiklikler eşitlendiğinde (birkaç iş parçacığı dize arabelleğini okuduğunda / değiştirdiğinden).Burada bir örneğe bakın .
Temeller:
String
değişmez bir sınıftır, değiştirilemez.
StringBuilder
eklenebilir, değiştirilebilen veya kaldırılabilen ve sonuçta a'ya dönüştürülebilen değiştirilebilir bir sınıftır String
StringBuffer
.StringBuilder
StringBuilder
Nesnenize erişen tek bir iş parçacığının olduğu her durumda tercih etmelisiniz .
Ayrıntılar:
Ayrıca StringBuilder/Buffers
sihir olmadığını, sadece Array'ı destek nesnesi olarak kullandıklarını ve Array'ın dolduğunda yeniden tahsis edilmesi gerektiğini unutmayın. Emin olun ve StringBuilder/Buffer
her .append()
çağrıldığında sürekli olarak yeniden boyutlandırılmaları gerekmeyen yerlerde nesnelerinizi yeterince büyük oluşturun .
Yeniden boyutlandırma çok dejenere olabilir. Temel olarak Array Array'ı her genişletilmesi gerektiğinde mevcut boyutunun 2 katına göre yeniden boyutlandırır. Bu, büyük miktarlarda RAM tahsis edilmesine ve StringBuilder/Buffer
sınıflar büyümeye başladığında kullanılmamasına neden olabilir .
Java perde arkasında String x = "A" + "B";
kullanır StringBuilder
. Yani basit vakalar için kendi davalarınızı ilan etmenin bir yararı yoktur. Ancak String
, 4k'den küçük olan büyük nesneler oluşturuyorsanız, bildirme StringBuilder sb = StringBuilder(4096);
, birleştirme işleminden veya yalnızca 16 karakterden oluşan varsayılan kurucuyu kullanmaktan çok daha etkilidir . Eğer String
10k'dan az olacaksanız, güvenli olmak için yapıcı ile 10k değerine başlatın . Ancak 10k olarak başlatılırsa, 10k'dan fazla 1 karakter yazarsanız, yeniden tahsis edilir ve 20k diziye kopyalanır. Bu yüzden yüksek başlatmak düşükten daha iyidir.
Otomatik yeniden boyutlandırma durumunda, 17. karakterde destek Array yeniden tahsis edilir ve 32 karaktere kopyalanır, 33. karakterde bu tekrar olur ve Array'ı yeniden tahsis edip 64 karaktere kopyalarsınız. Bunun bir çok yeniden tahsis ve kopyaya nasıl yozlaştığını görebilirsiniz, bu StringBuilder/Buffer
da ilk etapta kullanmaktan kaçınmaya çalıştığınız şeydir .
Bu, AbstractStringBuilder için JDK 6 Kaynak kodundan
void expandCapacity(int minimumCapacity) {
int newCapacity = (value.length + 1) * 2;
if (newCapacity < 0) {
newCapacity = Integer.MAX_VALUE;
} else if (minimumCapacity > newCapacity) {
newCapacity = minimumCapacity;
}
value = Arrays.copyOf(value, newCapacity);
}
En iyi uygulama, StringBuilder/Buffer
elden ne kadar büyük String
olacağını bilmiyorsanız ihtiyacınız olacağını düşündüğünüzden biraz daha büyük başlatmaktır, ancak tahmin edebilirsiniz. İhtiyacınız olandan biraz daha fazla bellek ayırma işlemi, birçok yeniden ayırma ve kopyadan daha iyi olacaktır.
Ayrıca , çoğu durumda sadece kaçınmaya çalıştığınız dejenere yeniden ayırma ve kopyalama döngüsünü başlatacak olan String + 16 karakterlerinin boyutunu ayıracak StringBuilder/Buffer
şekilde bir a ile String
başlamaya dikkat edin. Aşağıdakiler doğrudan Java 6 kaynak kodundan alınmıştır.
public StringBuilder(String str) {
super(str.length() + 16);
append(str);
}
Şans eseri, StringBuilder/Buffer
oluşturduğunuz ve oluşturucu yapıcıyı kontrol edemediğiniz bir örnekle sonuçlanırsanız , dejenere yeniden tahsis ve kopyalama davranışından kaçınmanın bir yolu vardır. Sonuçlarınızın sığacağından .ensureCapacity()
emin olmak istediğiniz boyutta arayın String
.
Alternatifler:
Bir not olarak, eğer gerçekten ağır String
bina ve manipülasyon yapıyorsanız , Halatlar olarak adlandırılan çok daha performans odaklı bir alternatif var .
Başka bir alternatif, StringList
alt sınıflandırma yoluyla bir uygulama oluşturmak ve listenin ArrayList<String>
her .append()
ve diğer mutasyon işlemlerindeki karakter sayısını izlemek için sayaçlar eklemek , daha sonra tam olarak ihtiyacınız olan boyuttan .toString()
bir tane oluşturmak ve listeyi oluşturmak ve oluşturmak için geçersiz kılmaktır . StringBuilder
çıktı, hatta StringBuilder
bir örnek değişkeni yapabilir ve sonuçları 'önbellek' .toString()
ve sadece bir şey değiştiğinde bunu yeniden oluşturmak zorunda.
Ayrıca String.format()
, daha iyi hale getirdikçe derleyici tarafından optimize edilebilen sabit formatlı çıktı oluştururken de unutmayın .
String x = "A" + "B";
gerçekten StringBuilder olmak derlemek? Neden sadece derleme yapmaz String x = "AB";
, yalnızca derleme zamanında bileşenler bilinmiyorsa bir StringBuilder kullanmalıdır.
Yani, birleştirme için mi?
Gerçek dünya örneği: Diğerlerinden yeni bir dize oluşturmak istiyorsunuz .
Örneğin bir mesaj göndermek için:
sicim
String s = "Dear " + user.name + "<br>" +
" I saw your profile and got interested in you.<br>" +
" I'm " + user.age + "yrs. old too"
StringBuilder
String s = new StringBuilder().append.("Dear ").append( user.name ).append( "<br>" )
.append(" I saw your profile and got interested in you.<br>")
.append(" I'm " ).append( user.age ).append( "yrs. old too")
.toString()
Veya
String s = new StringBuilder(100).appe..... etc. ...
// The difference is a size of 100 will be allocated upfront as fuzzy lollipop points out.
StringBuffer (sözdizimi tam olarak StringBuilder ile aynıdır, efektler farklıdır)
hakkında
StringBuffer
vs. StringBuilder
İlki eşzamanlıdır ve daha sonra değildir.
Tek bir iplik (vakaların% 90 olan) içinde birkaç kez çağırmak Yani, eğer StringBuilder
çalışacak kadar o iplik kilit sahibi olmadığını görmek için durmayacak çünkü daha hızlı.
Bu nedenle, kullanılması tavsiye edilir StringBuilder
(elbette aynı anda birden fazla iş parçacığına erişiminiz yoksa, bu nadirdir)
String
birleştirme ( + operatörünü kullanarak ) StringBuilder
altında derleyici kullanmak için derleyici tarafından optimize edilebilir , bu yüzden artık Java'nın eski günlerinde endişelenecek bir şey değil, bu herkesin her ne pahasına kaçınılması gerektiğini söylediği bir şeydi, çünkü her birleştirme yeni bir String nesnesi oluşturdu. Modern derleyiciler artık bunu yapmıyor, ancak StringBuilder
"eski" bir derleyici kullanmanız durumunda bunun yerine kullanmak iyi bir uygulamadır .
Düzenle
Sadece merak edenler için, derleyicinin bu sınıf için yaptığı şey budur:
class StringConcatenation {
int x;
String literal = "Value is" + x;
String builder = new StringBuilder().append("Value is").append(x).toString();
}
javap -c StringConcatenation
Compiled from "StringConcatenation.java"
class StringConcatenation extends java.lang.Object{
int x;
java.lang.String literal;
java.lang.String builder;
StringConcatenation();
Code:
0: aload_0
1: invokespecial #1; //Method java/lang/Object."<init>":()V
4: aload_0
5: new #2; //class java/lang/StringBuilder
8: dup
9: invokespecial #3; //Method java/lang/StringBuilder."<init>":()V
12: ldc #4; //String Value is
14: invokevirtual #5; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
17: aload_0
18: getfield #6; //Field x:I
21: invokevirtual #7; //Method java/lang/StringBuilder.append:(I)Ljava/lang/StringBuilder;
24: invokevirtual #8; //Method java/lang/StringBuilder.toString:()Ljava/lang/String;
27: putfield #9; //Field literal:Ljava/lang/String;
30: aload_0
31: new #2; //class java/lang/StringBuilder
34: dup
35: invokespecial #3; //Method java/lang/StringBuilder."<init>":()V
38: ldc #4; //String Value is
40: invokevirtual #5; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
43: aload_0
44: getfield #6; //Field x:I
47: invokevirtual #7; //Method java/lang/StringBuilder.append:(I)Ljava/lang/StringBuilder;
50: invokevirtual #8; //Method java/lang/StringBuilder.toString:()Ljava/lang/String;
53: putfield #10; //Field builder:Ljava/lang/String;
56: return
}
5 - 27 arasındaki satırlar "değişmez" adlı Dize içindir
31-53 numaralı satırlar "builder" adlı Dize içindir
Fark yok, her iki dize için de aynı kod yürütülür.
StringBuilder
Ödevin sağ tarafında bir Yapılacaklar Dizesi birleştirme kullanmak genellikle iyi bir uygulama DEĞİLDİR . İyi bir uygulama, dediğiniz gibi sahnelerin arkasında bir StringBuilder kullanır. Dahası, örneğiniz "a" + "b"
tek bir değişmez olarak derlenir, "ab"
ancak kullanırsanız StringBuilder
iki gereksiz çağrıyla sonuçlanır append()
.
"a"+"b"
ama dize birleştirme hakkında ne olduğunu söylemek için açık olarak değiştirin. Söylemediğiniz şey, bunu yapmak için neden iyi bir uygulama değil. (Modern) bir derleyici tam da bunu yapar. @fuzzy, katılıyorum, özellikle son dizenin boyutunun ne olacağını bildiğinizde (aprox).
-------------------------------------------------- -------------------------------- String StringBuffer StringBuilder -------------------------------------------------- -------------------------------- Depolama Alanı | Sabit Dize Havuzu Yığın Öbek Değiştirilebilir | Hayır (değiştirilemez) Evet (değiştirilebilir) Evet (değiştirilebilir) Konu Güvenli | Evet Evet Hayır Performans | Hızlı Çok yavaş Hızlı -------------------------------------------------- --------------------------------
synchronised
ve nedeni budur .
sicim
String class
Karakter dizeleri temsil eder. Java programındaki tüm dize değişmezleri "abc"
, bu sınıfın örnekleri olarak uygulanır.
Dize nesnelerdir değişmez onlar değiştiremezsiniz oluşturulduktan sonra. ( Dizeler sabittir )
String sonra bu dizeleri saklanacaktır yapıcısı veya yöntemi kullanılarak oluşturulursa Öbek Bellek yanı sıra SringConstantPool
. Ancak havuza kaydetmeden önce, intern()
eşittir yöntemini kullanarak havuzdaki aynı içeriğe sahip nesnenin kullanılabilirliğini kontrol etme yöntemini çağırır . Havuzda String-copy varsa referansı döndürür. Aksi takdirde, havuza String nesnesi eklenir ve başvuruyu döndürür.
+
) ve diğer nesnelerin dizelere dönüştürülmesi için özel destek sağlar . Dize birleştirmesi, StringBuilder (veya StringBuffer) sınıfı ve ekleme yöntemiyle uygulanır.String heapSCP = new String("Yash");
heapSCP.concat(".");
heapSCP = heapSCP + "M";
heapSCP = heapSCP + 777;
// For Example: String Source Code
public String concat(String str) {
int otherLen = str.length();
if (otherLen == 0) {
return this;
}
int len = value.length;
char buf[] = Arrays.copyOf(value, len + otherLen);
str.getChars(buf, len);
return new String(buf, true);
}
Dize değişmezleri içinde saklanır StringConstantPool
.
String onlyPool = "Yash";
StringBuilder ve StringBuffer değiştirilebilir karakter dizisidir. Bu, kişinin bu nesnelerin değerini değiştirebileceği anlamına gelir. StringBuffer, StringBuilder ile aynı yöntemlere sahiptir, ancak StringBuffer'daki her yöntem iş parçacığı açısından güvenli olacak şekilde senkronize edilir.
StringBuffer ve StringBuilder verileri yalnızca yeni işleç kullanılarak oluşturulabilir. Böylece, Heap belleğinde saklanırlar.
StringBuilder örneklerinin birden çok iş parçacığı tarafından kullanılması güvenli değildir. Bu tür bir senkronizasyon gerekiyorsa, StringBuffer'ın kullanılması önerilir.
StringBuffer threadSafe = new StringBuffer("Yash");
threadSafe.append(".M");
threadSafe.toString();
StringBuilder nonSync = new StringBuilder("Yash");
nonSync.append(".M");
nonSync.toString();
StringBuffer ve StringBuilder., replace(int start, int end, String str)
Ve gibi özel yöntemlere sahip
reverse()
.
Not : StringBuffer ve SringBuilder uygulama sağlar gibi değiştirilebilir
Appendable Interface
.
Hangisi ne zaman kullanılır.
Eğer bir değeri her seferinde değiştirmeyecekseniz Kullanmak daha iyidir String Class
. Generics'in bir parçası olarak, Comparable<T>
bir değeri Sıralamak veya karşılaştırmak istiyorsanız gidin String Class
.
//ClassCastException: java.lang.StringBuffer cannot be cast to java.lang.Comparable
Set<StringBuffer> set = new TreeSet<StringBuffer>();
set.add( threadSafe );
System.out.println("Set : "+ set);
Her seferinde değeri değiştirecekseniz StringBuffer'dan daha hızlı olan StringBuilder için gidin. Birden çok iş parçacığı değeri değiştiriyorsa StringBuffer için gidin.
Ayrıca, StringBuffer
iş parçacığı için güvenli, StringBuilder
değil.
Bu nedenle, farklı iş parçacıklarının ona eriştiği gerçek zamanlı bir durumda, StringBuilder
belirsiz bir sonuç elde edilebilir.
Java 5 veya daha yenisini kullanıyorsanız, StringBuilder
bunun yerine kullanmanız gerektiğini unutmayın StringBuffer
. API belgelerinden:
JDK 5 sürümünden itibaren bu sınıf, tek bir iş parçacığı tarafından kullanılmak üzere tasarlanmış eşdeğer bir sınıfla desteklenmiştir
StringBuilder
.StringBuilder
Aynı operasyonların tüm destekliyor ancak hiçbir senkronizasyon gerçekleştirir gibi, daha hızlı olduğu gibi sınıf genellikle bu bir tercih edilerek kullanılmalıdır.
Pratikte, bunu neredeyse hiçbir zaman aynı anda birden fazla iş parçacığından kullanmazsınız, bu nedenle yapılan senkronizasyon StringBuffer
neredeyse her zaman gereksiz ek yüktür.
Şahsen, gerçek bir dünya kullanımı olduğunu sanmıyorum StringBuffer
. Ne zaman bir karakter dizisini değiştirerek birden çok iş parçacığı arasında iletişim kurmak isterdim? Bu hiç de kullanışlı gelmiyor, ama belki de ışığı henüz görmedim :)
String ve diğer iki sınıf arasındaki fark String'in değişmez ve diğer ikisinin değiştirilebilir sınıflar olmasıdır.
Ama neden aynı amaçla iki sınıfımız var?
Sebep iş StringBuffer
parçacığı güvenli ve StringBuilder
değil olmasıdır.
StringBuilder
yeni bir sınıftır StringBuffer Api
ve tanıtıldı JDK5
ve tek iş parçacıklı bir ortamda çalışıyorsanız her zaman tavsiye edilir.Faster
Tüm Detaylar için http://www.codingeek.com/java/stringbuilder-and-stringbuffer-a-way-to-create-mutable-strings-in-java/
Java, dize sabittir. Değişmez olmak, Dize oluşturulduktan sonra değerini değiştiremeyeceğimizi kastediyoruz. StringBuffer değiştirilebilir. Bir StringBuffer nesnesi oluşturulduktan sonra, içeriği yeni bir nesne oluşturmak yerine nesnenin değerine ekleriz. StringBuilder , StringBuffer'a benzer, ancak iş parçacığı için güvenli değildir. StingBuilder yöntemleri senkronize edilmez ancak diğer Dizelerle karşılaştırıldığında Stringbuilder en hızlı çalışır. String, StringBuilder ve StringBuffer arasındaki farkı uygulayarak öğrenebilirsiniz .