Dengan 2 toString()
implementasi di bawah ini, mana yang lebih disukai:
public String toString(){
return "{a:"+ a + ", b:" + b + ", c: " + c +"}";
}
atau
public String toString(){
StringBuilder sb = new StringBuilder(100);
return sb.append("{a:").append(a)
.append(", b:").append(b)
.append(", c:").append(c)
.append("}")
.toString();
}
?
Lebih penting lagi, mengingat kita hanya memiliki 3 properti mungkin tidak membuat perbedaan, tetapi pada titik apa Anda akan beralih dari +
concat ke StringBuilder
?
java
performance
string
concatenation
stringbuilder
bukan sequitor
sumber
sumber
StringBuilder
berapa banyak ukuran untuk mengalokasikan dimuka jika tidak, jika kehabisan ruang, harus menggandakan ukuran dengan membuatchar[]
array baru kemudian menyalin data - yang mahal. Anda dapat menipu dengan memberikan ukuran dan kemudian tidak perlu untuk pembuatan array ini - jadi jika Anda berpikir string Anda akan ~ 100 char panjangnya maka Anda dapat mengatur StringBuilder ke ukuran itu dan tidak akan perlu meluas secara internal.Jawaban:
Versi 1 lebih disukai karena lebih pendek dan kompiler sebenarnya akan mengubahnya menjadi versi 2 - tidak ada perbedaan kinerja apa pun.
Pada titik di mana Anda menggabungkan dalam satu lingkaran - itu biasanya ketika kompiler tidak dapat menggantikan
StringBuilder
dengan sendirinya.sumber
To increase the performance of repeated string concatenation, a Java compiler _may_ use the StringBuffer class or a similar technique to reduce the number of intermediate String objects that are created by evaluation of an expression.
Kata kuncinya mungkin ada . Mengingat ini secara resmi opsional (walaupun kemungkinan besar dilaksanakan) tidakkah kita harus melindungi diri kita sendiri?Kuncinya adalah apakah Anda menulis satu rangkaian tunggal di satu tempat atau mengumpulkannya dari waktu ke waktu.
Untuk contoh yang Anda berikan, tidak ada gunanya secara eksplisit menggunakan StringBuilder. (Lihatlah kode yang dikompilasi untuk kasus pertama Anda.)
Tetapi jika Anda membangun string misalnya di dalam loop, gunakan StringBuilder.
Untuk memperjelas, dengan asumsi bahwa hugeArray berisi ribuan string, kode seperti ini:
sangat boros waktu dan memori dibandingkan dengan:
sumber
result += s;
juga (dalam contoh pertama)"{a:"+ a + ", b:" + b + ", c: " + c +"}";
Saya lebih memilih:
... karena pendek dan mudah dibaca.
Saya tidak akan mengoptimalkan ini untuk kecepatan kecuali jika Anda menggunakannya di dalam lingkaran dengan jumlah pengulangan yang sangat tinggi dan telah mengukur perbedaan kinerja.
Saya setuju, bahwa jika Anda harus mengeluarkan banyak parameter, formulir ini dapat membingungkan (seperti salah satu komentar katakan). Dalam hal ini saya akan beralih ke bentuk yang lebih mudah dibaca (mungkin menggunakan ToStringBuilder dari apache-commons - diambil dari jawaban matt b) dan mengabaikan kinerja lagi.
sumber
null
Dalam kebanyakan kasus, Anda tidak akan melihat perbedaan nyata antara kedua pendekatan, tetapi mudah untuk membuat skenario kasus terburuk seperti ini:
Outputnya adalah:
Masalahnya adalah bahwa untuk + = menambahkan ke string merekonstruksi string baru, sehingga biaya sesuatu yang linier dengan panjang string Anda (jumlah keduanya).
Jadi - untuk pertanyaan Anda:
Pendekatan kedua akan lebih cepat, tetapi kurang mudah dibaca dan sulit dipertahankan. Seperti yang saya katakan, dalam kasus spesifik Anda, Anda mungkin tidak akan melihat perbedaannya.
sumber
+=
, contoh aslinya adalah urutan+
, yang diubah oleh kompiler menjadi satustring.concat
panggilan. Hasil Anda tidak berlaku.Saya juga telah berbenturan dengan bos saya pada kenyataan apakah akan menggunakan append atau +. Ketika mereka menggunakan Append (saya masih tidak bisa mencari tahu seperti yang mereka katakan setiap kali sebuah objek baru dibuat). Jadi saya berpikir untuk melakukan beberapa penelitian dan pengembangan. Meskipun saya menyukai penjelasan Michael Borgwardt tetapi hanya ingin menunjukkan penjelasan jika seseorang benar-benar perlu tahu di masa depan.
dan pembongkaran kelas di atas keluar sebagai
Dari dua kode di atas Anda dapat melihat Michael benar. Dalam setiap kasus hanya satu objek SB yang dibuat.
sumber
Sejak Java 1.5, penggabungan satu baris sederhana dengan "+" dan StringBuilder.append () menghasilkan bytecode yang persis sama.
Jadi demi pembacaan kode, gunakan "+".
2 pengecualian:
sumber
Menggunakan versi terbaru Java (1.8) pembongkaran (
javap -c
) menunjukkan optimisasi yang diperkenalkan oleh kompiler.+
jugasb.append()
akan menghasilkan kode yang sangat mirip. Namun, akan bermanfaat untuk memeriksa perilaku jika kita menggunakan+
dalam for loop.Menambahkan string menggunakan + dalam for for loop
Jawa:
ByteCode :(
for
loop excerpt)Menambahkan string menggunakan stringbuilder.append
Jawa:
ByteCdoe :(
for
loop excerpt)Ada sedikit perbedaan mencolok . Dalam kasus pertama, di mana
+
digunakan, baruStringBuilder
dibuat untuk masing-masing untuk iterasi loop dan hasil yang dihasilkan disimpan dengan melakukantoString()
panggilan (29 hingga 41). Jadi, Anda menghasilkan String menengah yang benar-benar tidak Anda perlukan saat menggunakan+
operator dalamfor
loop.sumber
Di Java 9 versi 1 harus lebih cepat karena dikonversi menjadi
invokedynamic
panggilan. Rincian lebih lanjut dapat ditemukan di JEP-280 :sumber
Untuk alasan kinerja, penggunaan
+=
(String
penggabungan) tidak disarankan. Alasannya adalah: JavaString
tidak berubah, setiap kali penggabungan baru dilakukan, baruString
dibuat (yang baru memiliki sidik jari yang berbeda dari yang lebih lama yang sudah ada di kumpulan String ). Membuat string baru memberi tekanan pada GC dan memperlambat program: pembuatan objek itu mahal.Kode di bawah ini harus membuatnya lebih praktis dan jelas pada saat bersamaan.
Hasil untuk lari dilaporkan di bawah ini.
Tidak mempertimbangkan hasil untuk 1 concatenation (JIT belum melakukan tugasnya), bahkan untuk 10 concatenation penalti kinerja relevan; untuk ribuan penggabungan, perbedaannya sangat besar.
Pelajaran yang dapat dipetik dari percobaan yang sangat cepat ini (mudah direproduksi dengan kode di atas): jangan pernah gunakan
+=
untuk menyatukan senar, bahkan dalam kasus yang sangat mendasar di mana beberapa penggabungan diperlukan (seperti dikatakan, membuat string baru tetap mahal dan tetap menekan pada GC).sumber
Lihat contoh di bawah ini:
Keluaran:
Ketika panjang string meningkat, begitu juga waktu penggabungan.
Di situlah
StringBuilder
pasti diperlukan.Seperti yang Anda lihat, gabungan:,
UUID.randomUUID()+"---"
tidak terlalu mempengaruhi waktu.PS: Saya tidak berpikir Kapan menggunakan StringBuilder di Jawa adalah duplikat dari ini.
Pertanyaan ini berbicara tentang
toString()
yang sebagian besar kali tidak melakukan rangkaian string besar.Pembaruan 2019
Sejak
java8
saat itu, banyak hal berubah sedikit. Tampaknya sekarang (java13), waktu penyatuan+=
praktis sama denganstr.concat()
. NamunStringBuilder
waktu penggabungan masih konstan . (Posting asli di atas sedikit diedit untuk menambah lebih banyak keluaran verbose)Patut dicatat juga
bytecode:8/java.version:13
kombinasi memiliki manfaat kinerja yang baik dibandingkan denganbytecode:8/java.version:8
sumber
java13
yang kini berbeda. Tapi saya pikir kesimpulan utamanya tetap sama.Apache Commons-Lang memiliki kelas ToStringBuilder yang super mudah digunakan. Itu melakukan pekerjaan yang baik dari kedua penanganan append-logic serta memformat bagaimana Anda ingin toString Anda terlihat.
Akan mengembalikan output yang terlihat seperti
com.blah.YourClass@abc1321f[a=whatever, b=foo]
.Atau dalam bentuk yang lebih kental menggunakan chaining:
Atau jika Anda ingin menggunakan refleksi untuk memasukkan setiap bidang kelas:
Anda juga dapat menyesuaikan gaya ToString jika Anda mau.
sumber
Jadikan metode toString terbaca sebanyak mungkin!
Satu-satunya pengecualian untuk ini dalam buku saya adalah jika Anda dapat membuktikan kepada saya bahwa ia menghabiskan sumber daya yang signifikan :) (Ya, ini berarti membuat profil)
Perhatikan juga bahwa kompiler Java 5 menghasilkan kode lebih cepat daripada pendekatan "StringBuffer" tulisan tangan yang digunakan dalam versi Java yang lebih lama. Jika Anda menggunakan "+" ini, peningkatan di masa mendatang akan datang secara gratis.
sumber
Tampaknya ada beberapa perdebatan apakah menggunakan StringBuilder masih diperlukan dengan kompiler saat ini. Jadi saya pikir saya akan memberikan 2 sen pengalaman saya.
Saya memiliki
JDBC
set hasil 10k catatan (ya, saya membutuhkan semuanya dalam satu batch.) Menggunakan + operator memakan waktu sekitar 5 menit pada mesin saya denganJava 1.8
. MenggunakanstringBuilder.append("")
membutuhkan waktu kurang dari satu detik untuk permintaan yang sama.Jadi perbedaannya sangat besar. Di dalam lingkaran
StringBuilder
jauh lebih cepat.sumber
Rangkaian string yang bijak berkinerja baik menggunakan '+' lebih mahal karena harus membuat salinan String yang sama sekali baru karena String tidak dapat diubah di java. Ini memainkan peran tertentu jika penggabungan sangat sering, misalnya: di dalam lingkaran. Berikut ini yang disarankan IDEA saya ketika saya berupaya melakukan hal seperti itu:
Aturan umum:
Berikut ini adalah blog Jon Skeet yang bagus untuk topik ini.
sumber
Dapatkah saya menunjukkan bahwa jika Anda akan beralih ke koleksi dan menggunakan StringBuilder, Anda mungkin ingin memeriksa Apache Commons Lang dan StringUtils.join () (dalam berbagai rasa)?
Terlepas dari kinerja, itu akan menghemat Anda harus membuat StringBuilders dan untuk loop untuk apa yang tampaknya seperti yang kesekian kalinya.
sumber
Inilah yang saya periksa di Java8
Menggunakan StringBuilder
sumber
Saya pikir kita harus pergi dengan pendekatan append StringBuilder. Alasannya adalah:
String concatenate akan membuat objek string baru setiap kali (Karena String adalah objek yang tidak dapat diubah), maka ia akan membuat 3 objek.
Dengan String builder, hanya satu objek yang akan dibuat [StringBuilder bisa berubah] dan string selanjutnya ditambahkan ke sana.
sumber
Untuk string sederhana seperti itu saya lebih suka menggunakan
Agar, saya akan mengatakan metode yang lebih disukai untuk membangun sebuah string menggunakan StringBuilder, String # concat (), kemudian operator + yang kelebihan beban. StringBuilder adalah peningkatan kinerja yang signifikan ketika bekerja string besar seperti menggunakan operator + adalah penurunan besar dalam kinerja (penurunan secara eksponensial besar ketika ukuran String meningkat). Satu masalah dengan menggunakan .concat () adalah ia bisa melempar NullPointerExceptions.
sumber