Pertanyaan lain: mengapa Anda menggunakan SB hanya untuk satu iterasi loop? Apakah ada iterasi batin lainnya? SB tidak layak jika Anda hanya ingin melakukan A + B + C + D (kompiler Java secara internal akan menggunakan SB). Ini membantu jika Anda ingin menambahkan bagian-bagian string secara bersyarat, tetapi sebaliknya ... cukup gunakan "+".
helios
Jawaban:
135
Salah satu opsinya adalah menggunakan metode delete sebagai berikut:
StringBuffer sb =newStringBuffer();for(int n =0; n <10; n++){
sb.append("a");// This will clear the buffer
sb.delete(0, sb.length());}
Opsi lain (pembersih bit) menggunakan setLength (int len) :
Sesuatu yang sedikit lebih baik adalah dengan mendeklarasikan StringBuffer di dalam loop.
Mark Elliot
11
Ah, saya pikir sb.setLength (0); lebih bersih dan lebih efisien daripada mendeklarasikannya di dalam loop. Solusi Anda bertentangan dengan manfaat kinerja menggunakan StringBuffer ...
Jon
6
Saya pikir manfaat kinerja berasal dari mutabilitas string, bukan dari menyimpan instantiation. berikut adalah tes cepat dari 1e8 iterasi: loop dalam (2,97s): ideone.com/uyyTL14w , loop luar (2,87s): ideone.com/F9lgsIxh
Mark Elliot
6
Berbicara tentang kinerja: Kecuali kode Anda diakses dalam skenario multi-utas, Anda harus menggunakan StringBuilder daripada StringBuffer - lihat javadoc: "Jika memungkinkan, disarankan agar kelas ini digunakan dalam preferensi untuk StringBuffer karena akan lebih cepat di bawah sebagian besar implementasi ".
Rahel Lüthy
4
Satu-satunya keuntungan dari menciptakan SB di luar tidak kehilangan karakter internal (berpotensi panjang) darinya. Jika di iterator pertama sudah cukup besar, loop kedua tidak perlu mengubah ukuran char []. Tetapi untuk mendapatkan keuntungan, "metode yang jelas" harus mempertahankan ukuran array internal. setLength melakukan itu tetapi juga menyetel ke \ u0000 semua karakter yang tidak digunakan di SB, jadi performanya kurang dari sekadar membuat SB baru dengan kapasitas awal yang baik. Mendeklarasikan di dalam loop lebih baik.
helios
48
Cara termudah untuk menggunakan kembali StringBufferadalah dengan menggunakan metode inisetLength()
sb.setLength(0);// It will just discard the previous data, which will be garbage collected later.
Atau gunakan:
sb.delete(0, sb.length());// A bit slower as it is used to delete sub sequence.
CATATAN
Hindari mendeklarasikan StringBufferatau StringBuilderobjek dalam loop lain itu akan membuat objek baru dengan setiap iterasi. Membuat objek membutuhkan sumber daya sistem, ruang dan juga membutuhkan waktu. Jadi untuk jangka panjang, hindari mendeklarasikannya dalam loop jika memungkinkan.
Saya sarankan membuat yang baru StringBuffer(atau bahkan lebih baik, StringBuilder) untuk setiap iterasi. Perbedaan kinerja benar-benar dapat diabaikan, tetapi kode Anda akan lebih pendek dan sederhana.
Jika Anda memiliki bukti perbedaan kinerja tersebut, silakan bagikan. (Saya juga akan senang melihat statistik di mana Java sebagian besar digunakan, dan di mana definisi "sebagian besar".)
Eli Acherkan
1
Telah diketahui bahwa alokasi (kata kunci baru di Java) lebih mahal daripada hanya mengubah beberapa bidang dari objek yang sama. Untuk "sebagian besar", yang sangat dapat Anda ganti, ada lebih dari 1,5 Miliar Perangkat Android, semuanya menggunakan Java.
Louis CAD
1
Saya setuju bahwa dalam beberapa kasus, keterbacaan kode lebih penting daripada kinerja, tetapi dalam kasus ini, itu hanya satu baris kode! Dan Anda dapat menjalankan benchmark yang akan membuktikan bahwa alokasi dan pembuatan objek, ditambah pengumpulan sampah lebih mahal daripada tidak melakukannya sama sekali. Karena kita berada dalam satu lingkaran, itu lebih dari relevan.
Louis CAD
1
Saya juga menganut pandangan Knuth, tetapi sudut pandangnya tidak selalu benar. Menambahkan hanya satu baris untuk mendapatkan siklus CPU dan memori sama sekali tidak jahat. Anda mengambil ide terlalu lurus. Perhatikan bahwa loop biasanya diulang berkali-kali. Sebuah loop dapat diulang ribuan kali, yang dapat memakan megabyte yang berharga di ponsel (dan juga di server atau komputer) jika tidak dioptimalkan dengan hati-hati.
Louis CAD
1
Saya pikir kami berdua menyatakan sudut pandang kami dengan cukup jelas, dan saya merasa bahwa diskusi lebih lanjut tidak akan bermanfaat untuk bagian komentar ini. Jika Anda merasa jawaban saya tidak benar, menyesatkan, atau tidak lengkap, Anda - atau siapa pun - boleh mengedit dan / atau menolaknya.
Jawaban udah bagus disana. Cukup tambahkan hasil benchmark untuk perbedaan kinerja StringBuffer dan StringBuild gunakan contoh baru dalam loop atau gunakan setLength (0) dalam loop.
Ringkasannya adalah: Dalam lingkaran besar
StringBuilder jauh lebih cepat daripada StringBuffer
Buat instance StringBuilder baru dalam loop tidak ada perbedaan dengan setLength (0). (setLength (0) memiliki keuntungan yang sangat sangat kecil daripada membuat instance baru.)
StringBuffer lebih lambat dari StringBuilder dengan membuat instance baru secara berulang
setLength (0) dari StringBuffer sangat lambat daripada membuat instance baru dalam perulangan.
Tolok ukur yang sangat sederhana (Saya baru saja mengubah kode secara manual dan melakukan pengujian yang berbeda):
publicclassStringBuilderSpeed{publicstaticfinalchar ch[]=newchar[]{'a','b','c','d','e','f','g','h','i'};publicstaticvoid main(String a[]){int loopTime =99999999;long startTime =System.currentTimeMillis();StringBuilder sb =newStringBuilder();for(int i =0; i < loopTime; i++){for(char c : ch){
sb.append(c);}
sb.setLength(0);}long endTime =System.currentTimeMillis();System.out.println("Time cost: "+(endTime - startTime));}
}
Instance StringBuilder baru dalam loop: Biaya waktu: 3693, 3862, 3624, 3742
Instance StringBuffer baru dalam loop: Biaya waktu: 8327, 8324, 8284
StringBuffer setLength Waktu biaya: 22878, 23017, 22894
Sekali lagi StringBuilder setLength untuk memastikan labtop saya tidak mendapat masalah untuk digunakan selama itu untuk StringBuffer setLength :-) Biaya waktu: 3448
Jawaban:
Salah satu opsinya adalah menggunakan metode delete sebagai berikut:
Opsi lain (pembersih bit) menggunakan setLength (int len) :
Lihat Javadoc untuk info lebih lanjut:
sumber
Cara termudah untuk menggunakan kembali
StringBuffer
adalah dengan menggunakan metode inisetLength()
public void setLength(int newLength)
Anda mungkin memiliki kasus seperti ini
sumber
setLength
bukansetlength
.Anda memiliki dua pilihan:
Salah satu penggunaan:
Atau gunakan:
CATATAN
Hindari mendeklarasikan
StringBuffer
atauStringBuilder
objek dalam loop lain itu akan membuat objek baru dengan setiap iterasi. Membuat objek membutuhkan sumber daya sistem, ruang dan juga membutuhkan waktu. Jadi untuk jangka panjang, hindari mendeklarasikannya dalam loop jika memungkinkan.sumber
sumber
Saya sarankan membuat yang baru
StringBuffer
(atau bahkan lebih baik,StringBuilder
) untuk setiap iterasi. Perbedaan kinerja benar-benar dapat diabaikan, tetapi kode Anda akan lebih pendek dan sederhana.sumber
Pemakaian:
untuk keterbacaan, saya rasa ini adalah solusi terbaik.
sumber
Jawaban udah bagus disana. Cukup tambahkan hasil benchmark untuk perbedaan kinerja StringBuffer dan StringBuild gunakan contoh baru dalam loop atau gunakan setLength (0) dalam loop.
Ringkasannya adalah: Dalam lingkaran besar
Tolok ukur yang sangat sederhana (Saya baru saja mengubah kode secara manual dan melakukan pengujian yang berbeda):
}
Instance StringBuilder baru dalam loop: Biaya waktu: 3693, 3862, 3624, 3742
StringBuilder setLength: Biaya waktu: 3465, 3421, 3557, 3408
Instance StringBuffer baru dalam loop: Biaya waktu: 8327, 8324, 8284
StringBuffer setLength Waktu biaya: 22878, 23017, 22894
Sekali lagi StringBuilder setLength untuk memastikan labtop saya tidak mendapat masalah untuk digunakan selama itu untuk StringBuffer setLength :-) Biaya waktu: 3448
sumber
saya pikir kode ini lebih cepat.
sumber