Tolong beritahu saya situasi real time untuk membandingkan String
, StringBuffer
dan StringBuilder
?
Tolong beritahu saya situasi real time untuk membandingkan String
, StringBuffer
dan StringBuilder
?
Jawaban:
Perbedaan Mutabilitas:
String
adalah kekal , jika Anda mencoba untuk mengubah nilai-nilai mereka, objek lain akan dibuat, sedangkan StringBuffer
dan StringBuilder
yang bisa berubah sehingga mereka dapat mengubah nilai-nilai mereka.
Perbedaan Thread-Safety:
Perbedaan antara StringBuffer
dan StringBuilder
apakah itu StringBuffer
aman-thread. Jadi ketika aplikasi perlu dijalankan hanya dalam satu utas maka lebih baik digunakan StringBuilder
. StringBuilder
lebih efisien daripada StringBuffer
.
Situasi:
String
objek tidak dapat diubah.StringBuilder
cukup baik.StringBuffer
karena StringBuffer
sinkron sehingga Anda memiliki keamanan utas.Strings
ketika kita mengubah nilai objek lain dibuat. Apakah referensi objek lama dibatalkan sehingga mungkin sampah yang dikumpulkan oleh GC
atau bahkan sampah yang dikumpulkan?
String
dengan StringBuilder
?
String
saat struktur yang tidak dapat diubah sesuai; memperoleh urutan karakter baru dari a String
dapat 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).StringBuilder
saat Anda perlu membuat urutan karakter yang bisa berubah, biasanya untuk menyatukan beberapa urutan karakter secara bersamaan.StringBuffer
dalam 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:
String
adalah kelas yang tidak dapat diubah, tidak dapat diubah.
StringBuilder
adalah kelas yang bisa berubah yang dapat ditambahkan ke, karakter diganti atau dihapus dan akhirnya dikonversi ke String
StringBuffer
adalah versi asli disinkronkanStringBuilder
Anda harus memilih StringBuilder
dalam semua kasus di mana Anda hanya memiliki satu utas mengakses objek Anda.
Rinciannya:
Juga perhatikan bahwa StringBuilder/Buffers
itu bukan sihir, mereka hanya menggunakan Array sebagai objek pendukung dan bahwa Array harus dialokasikan kembali ketika sudah penuh. Pastikan dan buat StringBuilder/Buffer
objek 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/Buffer
kelas mulai tumbuh besar.
Di Jawa String x = "A" + "B";
menggunakan di StringBuilder
belakang layar. Jadi untuk kasus-kasus sederhana tidak ada manfaatnya menyatakan milik Anda sendiri. Tetapi jika Anda membangun String
objek 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 String
akan 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/Buffer
di 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/Buffer
sedikit lebih besar dari yang Anda pikir akan Anda butuhkan jika Anda tidak tahu berapa besar String
akan 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/Buffer
dengan String
yang 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/Buffer
yang 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 String
sesuai.
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 StringList
implementasi 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 StringBuilder
ukuran persis yang Anda butuhkan dan mengulang-ulang daftar dan membangun output, Anda bahkan dapat membuat StringBuilder
variabel 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), StringBuilder
akan 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)
String
Rangkaian ( menggunakan operator + ) dapat dioptimalkan oleh kompiler untuk digunakan di StringBuilder
bawahnya, 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 StringBuilder
sebagai 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.
StringBuilder
gabungan 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 StringBuilder
akan 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 -------------------------------------------------- --------------------------------
synchronised
dan itulah sebabnya .
Tali
The String class
mewakili 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, StringBuffer
aman-thread, yang StringBuilder
tidak.
Jadi dalam situasi waktu nyata ketika utas yang berbeda mengaksesnya, StringBuilder
dapat memiliki hasil yang tidak ditentukan.
Catatan bahwa jika Anda menggunakan Java 5 atau yang lebih baru, Anda harus menggunakan StringBuilder
bukan StringBuffer
. Dari dokumentasi API:
Pada rilis JDK 5, kelas ini telah dilengkapi dengan kelas setara yang dirancang untuk digunakan oleh satu utas
StringBuilder
,. TheStringBuilder
kelas 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 StringBuffer
dilakukannya 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 StringBuffer
Thread aman dan StringBuilder
tidak.
StringBuilder
adalah kelas baru StringBuffer Api
dan diperkenalkan JDK5
dan 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.