Tolong beritahu saya situasi real time untuk membandingkan String, StringBufferdan StringBuilder?
Tolong beritahu saya situasi real time untuk membandingkan String, StringBufferdan StringBuilder?
Jawaban:
Perbedaan Mutabilitas:
Stringadalah kekal , jika Anda mencoba untuk mengubah nilai-nilai mereka, objek lain akan dibuat, sedangkan StringBufferdan StringBuilderyang bisa berubah sehingga mereka dapat mengubah nilai-nilai mereka.
Perbedaan Thread-Safety:
Perbedaan antara StringBufferdan StringBuilderapakah itu StringBufferaman-thread. Jadi ketika aplikasi perlu dijalankan hanya dalam satu utas maka lebih baik digunakan StringBuilder. StringBuilderlebih efisien daripada StringBuffer.
Situasi:
Stringobjek tidak dapat diubah.StringBuildercukup baik.StringBufferkarena StringBuffersinkron sehingga Anda memiliki keamanan utas.Stringsketika kita mengubah nilai objek lain dibuat. Apakah referensi objek lama dibatalkan sehingga mungkin sampah yang dikumpulkan oleh GCatau bahkan sampah yang dikumpulkan?
Stringdengan StringBuilder?
Stringsaat struktur yang tidak dapat diubah sesuai; memperoleh urutan karakter baru dari a Stringdapat membawa penalti kinerja yang tidak dapat diterima, baik dalam waktu CPU atau memori (memperoleh substring adalah CPU yang efisien karena data tidak disalin, tetapi ini berarti jumlah data yang berpotensi jauh lebih besar mungkin tetap dialokasikan).StringBuildersaat Anda perlu membuat urutan karakter yang bisa berubah, biasanya untuk menyatukan beberapa urutan karakter secara bersamaan.StringBufferdalam keadaan yang sama Anda akan gunakan StringBuilder, tetapi ketika perubahan pada string yang mendasarinya harus disinkronkan (karena beberapa utas membaca / memodifikasi dalam buffer string).Lihat contoh di sini .
Dasar:
Stringadalah kelas yang tidak dapat diubah, tidak dapat diubah.
StringBuilderadalah kelas yang bisa berubah yang dapat ditambahkan ke, karakter diganti atau dihapus dan akhirnya dikonversi ke String
StringBufferadalah versi asli disinkronkanStringBuilder
Anda harus memilih StringBuilderdalam semua kasus di mana Anda hanya memiliki satu utas mengakses objek Anda.
Rinciannya:
Juga perhatikan bahwa StringBuilder/Buffersitu bukan sihir, mereka hanya menggunakan Array sebagai objek pendukung dan bahwa Array harus dialokasikan kembali ketika sudah penuh. Pastikan dan buat StringBuilder/Bufferobjek Anda cukup besar di tempat asalnya tidak harus selalu diukur ulang setiap kali .append()dipanggil.
Pengubahan ukuran bisa sangat memburuk. Ini pada dasarnya kembali ukuran Array dukungan untuk 2 kali ukuran saat ini setiap kali perlu diperluas. Ini dapat menyebabkan sejumlah besar RAM mendapatkan alokasi dan tidak digunakan ketika StringBuilder/Bufferkelas mulai tumbuh besar.
Di Jawa String x = "A" + "B";menggunakan di StringBuilderbelakang layar. Jadi untuk kasus-kasus sederhana tidak ada manfaatnya menyatakan milik Anda sendiri. Tetapi jika Anda membangun Stringobjek yang besar, katakanlah kurang dari 4k, maka menyatakan StringBuilder sb = StringBuilder(4096);jauh lebih efisien daripada penggabungan atau menggunakan konstruktor default yang hanya 16 karakter. Jika Anda Stringakan kurang dari 10k maka inisialisasi dengan konstruktor ke 10k agar aman. Tetapi jika diinisialisasi ke 10k maka Anda menulis 1 karakter lebih dari 10k, itu akan dialokasikan kembali dan disalin ke array 20k. Jadi menginisialisasi tinggi lebih baik daripada rendah.
Dalam kasus ukuran ulang otomatis, pada karakter ke-17, Array dukungan akan dialokasikan kembali dan disalin ke 32 karakter, pada karakter ke-33 ini terjadi lagi dan Anda bisa mengalokasikan kembali dan menyalin Array ke dalam 64 karakter. Anda dapat melihat bagaimana ini merosot ke banyak alokasi ulang dan salinan yang merupakan apa yang Anda benar-benar coba hindari menggunakan StringBuilder/Bufferdi tempat pertama.
Ini dari kode sumber JDK 6 untuk AbstractStringBuilder
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);
}
Praktik terbaik adalah menginisialisasi yang StringBuilder/Buffersedikit lebih besar dari yang Anda pikir akan Anda butuhkan jika Anda tidak tahu berapa besar Stringakan tetapi Anda bisa menebaknya. Satu alokasi memori yang sedikit lebih banyak daripada yang Anda butuhkan akan lebih baik daripada banyak alokasi ulang dan salinan.
Juga berhati-hatilah dalam menginisialisasi a StringBuilder/Bufferdengan Stringyang hanya akan mengalokasikan ukuran karakter String + 16, yang dalam kebanyakan kasus hanya akan memulai alokasi ulang yang merosot dan menyalin siklus yang Anda coba hindari. Berikut ini adalah langsung dari kode sumber Java 6.
public StringBuilder(String str) {
super(str.length() + 16);
append(str);
}
Jika Anda kebetulan berakhir dengan contoh StringBuilder/Bufferyang tidak Anda buat dan tidak dapat mengontrol konstruktor yang dipanggil, ada cara untuk menghindari perilaku alokasi ulang dan salin yang merosot. Panggil .ensureCapacity()dengan ukuran yang Anda inginkan untuk memastikan hasil Anda Stringsesuai.
Alternatif:
Sama seperti catatan, jika Anda melakukan pembangunan dan manipulasi yang sangat berat String , ada alternatif yang lebih berorientasi pada kinerja yang disebut Tali .
Alternatif lain, adalah membuat StringListimplementasi dengan subklasifikasi ArrayList<String>, dan menambahkan penghitung untuk melacak jumlah karakter pada setiap .append()dan operasi mutasi lainnya dari daftar, kemudian mengganti .toString()untuk membuat StringBuilderukuran persis yang Anda butuhkan dan mengulang-ulang daftar dan membangun output, Anda bahkan dapat membuat StringBuildervariabel instan dan 'cache' hasil .toString()dan hanya perlu menghasilkan kembali ketika sesuatu berubah.
Juga jangan lupa String.format()ketika membangun output terformat tetap, yang dapat dioptimalkan oleh kompiler karena mereka membuatnya lebih baik.
String x = "A" + "B";benar-benar mengkompilasi menjadi StringBuilder? Mengapa tidak dikompilasi saja String x = "AB";, seharusnya hanya menggunakan StringBuilder jika komponen tidak diketahui pada waktu kompilasi.
Apakah maksud Anda, untuk penggabungan?
Contoh dunia nyata: Anda ingin membuat string baru dari banyak lainnya .
Misalnya untuk mengirim pesan:
Tali
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()
Atau
String s = new StringBuilder(100).appe..... etc. ...
// The difference is a size of 100 will be allocated upfront as fuzzy lollipop points out.
StringBuffer (sintaksnya persis seperti dengan StringBuilder, efeknya berbeda)
Tentang
StringBuffer vs. StringBuilder
Yang pertama disinkronkan dan kemudian tidak.
Jadi, jika Anda menjalankannya beberapa kali dalam satu utas (yang merupakan 90% dari semua casing), StringBuilderakan berjalan jauh lebih cepat karena tidak akan berhenti untuk melihat apakah ia memiliki kunci utas.
Jadi, disarankan untuk menggunakan StringBuilder(kecuali tentu saja Anda memiliki lebih dari satu utas mengaksesnya pada saat yang sama, yang jarang terjadi)
StringRangkaian ( menggunakan operator + ) dapat dioptimalkan oleh kompiler untuk digunakan di StringBuilderbawahnya, jadi, itu bukan lagi sesuatu yang perlu dikhawatirkan, di masa tua Jawa, ini adalah sesuatu yang semua orang katakan harus dihindari dengan cara apa pun, karena setiap rangkaian membuat objek String baru. Kompiler modern tidak melakukan ini lagi, tetapi tetap merupakan praktik yang baik untuk digunakan StringBuildersebagai gantinya jika Anda menggunakan kompiler "lama".
sunting
Hanya untuk yang penasaran, inilah yang dilakukan oleh kompiler untuk kelas ini:
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
}
Baris bernomor 5 - 27 adalah untuk String yang bernama "literal"
Baris bernomor 31-53 untuk String bernama "builder"
Tidak ada perbedaan, kode yang sama persis dijalankan untuk kedua string.
StringBuildergabungan string to do di sisi kanan penugasan. Setiap implementasi yang baik akan menggunakan StringBuilder di belakang layar seperti yang Anda katakan. Selanjutnya, contoh Anda "a" + "b"akan dikompilasi menjadi satu literal "ab"tetapi jika Anda menggunakannya StringBuilderakan menghasilkan dua panggilan yang tidak perlu append().
"a"+"b"tetapi untuk mengatakan apa yang merupakan rangkaian String tentang saya mengubahnya menjadi eksplisit. Apa yang tidak Anda katakan adalah, mengapa bukan praktik yang baik untuk melakukannya. Itulah yang dilakukan oleh kompiler (modern). @ fuzzy, saya setuju, khususnya ketika Anda tahu ukuran string terakhir (aprox).
-------------------------------------------------- --------------------------------
String StringBuffer StringBuilder
-------------------------------------------------- --------------------------------
Area Penyimpanan | Constant String Pool Heap Heap
Dapat dimodifikasi | Tidak (tidak berubah) Ya (bisa berubah) Ya (bisa berubah)
Thread Aman | Ya, Tidak
Performa | Cepat Sangat lambat Cepat
-------------------------------------------------- --------------------------------
synchroniseddan itulah sebabnya .
Tali
The String classmewakili karakter string. Semua string literal dalam program Java, seperti "abc"diimplementasikan sebagai instance dari kelas ini.
Objek string tidak dapat diubah setelah dibuat, kita tidak dapat mengubah. ( String adalah konstanta )
Jika sebuah String dibuat menggunakan konstruktor atau metode maka string tersebut akan disimpan dalam Heap Memory juga SringConstantPool. Tetapi sebelum menyimpan di kolam itu memanggil intern()metode untuk memeriksa ketersediaan objek dengan konten yang sama di kolam menggunakan metode sama. Jika String-copy tersedia di Pool maka mengembalikan referensi. Jika tidak, objek String ditambahkan ke kumpulan dan mengembalikan referensi.
+), dan untuk konversi objek lain ke string. Rangkaian string diimplementasikan melalui kelas StringBuilder (atau StringBuffer) dan metode appendnya.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);
}
String literal disimpan di StringConstantPool.
String onlyPool = "Yash";
StringBuilder dan StringBuffer adalah urutan karakter yang bisa berubah. Itu berarti seseorang dapat mengubah nilai objek ini. StringBuffer memiliki metode yang sama dengan StringBuilder, tetapi setiap metode di StringBuffer disinkronkan sehingga aman untuk thread.
Data StringBuffer dan StringBuilder hanya dapat dibuat menggunakan operator baru. Jadi, mereka disimpan dalam memori Heap.
Contoh dari StringBuilder tidak aman untuk digunakan oleh banyak utas. Jika sinkronisasi seperti itu diperlukan maka disarankan agar StringBuffer digunakan.
StringBuffer threadSafe = new StringBuffer("Yash");
threadSafe.append(".M");
threadSafe.toString();
StringBuilder nonSync = new StringBuilder("Yash");
nonSync.append(".M");
nonSync.toString();
StringBuffer dan StringBuilder memiliki metode khusus seperti.,
replace(int start, int end, String str)Dan reverse().
CATATAN : StringBuffer dan SringBuilder bisa berubah karena mereka menyediakan implementasi
Appendable Interface.
Kapan harus menggunakan yang mana.
Jika a Anda tidak akan mengubah nilai setiap kali maka lebih baik Digunakan String Class. Sebagai bagian dari Generik jika Anda ingin Menyortir Comparable<T>atau membandingkan nilai, lalu gunakan 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);
Jika Anda akan mengubah nilai setiap kali pergi untuk StringBuilder yang lebih cepat dari StringBuffer. Jika beberapa utas mengubah nilai, gunakan StringBuffer.
Juga, StringBufferaman-thread, yang StringBuildertidak.
Jadi dalam situasi waktu nyata ketika utas yang berbeda mengaksesnya, StringBuilderdapat memiliki hasil yang tidak ditentukan.
Catatan bahwa jika Anda menggunakan Java 5 atau yang lebih baru, Anda harus menggunakan StringBuilderbukan StringBuffer. Dari dokumentasi API:
Pada rilis JDK 5, kelas ini telah dilengkapi dengan kelas setara yang dirancang untuk digunakan oleh satu utas
StringBuilder,. TheStringBuilderkelas umumnya harus digunakan dalam preferensi untuk yang satu ini, karena mendukung semua operasi yang sama tetapi lebih cepat, karena melakukan tidak ada sinkronisasi.
Dalam praktiknya, Anda hampir tidak akan pernah menggunakan ini dari banyak utas secara bersamaan, sehingga sinkronisasi yang StringBufferdilakukannya hampir selalu tidak perlu di atas kepala.
Secara pribadi, saya tidak berpikir ada gunanya menggunakan dunia nyata StringBuffer. Kapan saya ingin berkomunikasi antara banyak utas dengan memanipulasi urutan karakter? Kedengarannya tidak berguna sama sekali, tapi mungkin saya belum melihat cahaya :)
Perbedaan antara String dan dua kelas lainnya adalah bahwa String tidak dapat diubah dan dua lainnya adalah kelas yang bisa berubah.
Tetapi mengapa kita memiliki dua kelas untuk tujuan yang sama?
Alasannya adalah StringBufferThread aman dan StringBuildertidak.
StringBuilderadalah kelas baru StringBuffer Apidan diperkenalkan JDK5dan selalu disarankan jika Anda bekerja di lingkungan berulir tunggal seperti yang banyakFaster
Untuk Perincian Lengkap, Anda dapat membaca http://www.codingeek.com/java/stringbuilder-and-stringbuffer-a-way-to-create-mutable-strings-in-java/
Di java, String tidak dapat diubah. Menjadi kekal kita maksudkan bahwa sekali String dibuat, kita tidak bisa mengubah nilainya. StringBuffer bisa berubah. Setelah objek StringBuffer dibuat, kami hanya menambahkan konten ke nilai objek alih-alih membuat objek baru. StringBuilder mirip dengan StringBuffer tetapi tidak aman untuk thread. Metode StingBuilder tidak disinkronkan tetapi dibandingkan dengan String lainnya, Stringbuilder berjalan tercepat. Anda dapat mempelajari perbedaan antara String, StringBuilder dan StringBuffer dengan mengimplementasikannya.