Dengan asumsi String a dan b:
a += b
a = a.concat(b)
Di bawah tenda, apakah mereka hal yang sama?
Di sini concat didekompilasi sebagai referensi. Saya ingin dapat mendekompilasi +
operator juga untuk melihat apa yang dilakukannya.
public String concat(String s) {
int i = s.length();
if (i == 0) {
return this;
}
else {
char ac[] = new char[count + i];
getChars(0, count, ac, 0);
s.getChars(0, i, ac, count);
return new String(0, count + i, ac);
}
}
java
string
concatenation
shsteimer
sumber
sumber
+
bisa didekompilasi.StringBuffer
atauStringBuilder
- (utas tidak aman lebih cepat, sebagai gantinyaJawaban:
Tidak, tidak cukup.
Pertama, ada sedikit perbedaan dalam semantik. Jika
a
ininull
, makaa.concat(b)
melemparkanNullPointerException
tetapia+=b
akan memperlakukan nilai aslia
seolah-olah itunull
. Selain itu,concat()
metode ini hanya menerimaString
nilai sementara+
operator akan secara diam-diam mengubah argumen menjadi String (menggunakantoString()
metode untuk objek). Sehinggaconcat()
metode ini lebih ketat dalam apa yang diterimanya.Untuk melihat di bawah tenda, tulis kelas sederhana dengan
a += b;
Sekarang dibongkar dengan
javap -c
(termasuk dalam Sun JDK). Anda akan melihat daftar termasuk:Jadi,
a += b
sama denganThe
concat
metode harus lebih cepat. Namun, dengan lebih banyak stringStringBuilder
metode ini menang, setidaknya dalam hal kinerja.Kode sumber
String
danStringBuilder
(dan kelas dasar paket-privasinya) tersedia di src.zip dari Sun JDK. Anda dapat melihat bahwa Anda sedang membangun array char (mengubah ukuran sesuai kebutuhan) dan kemudian membuangnya ketika Anda membuat finalString
. Dalam praktiknya alokasi memori sangat cepat.Pembaruan: Seperti catatan Pawel Adamski, kinerja telah berubah di HotSpot yang lebih baru.
javac
masih menghasilkan kode yang persis sama, tetapi kode curang bytecode. Pengujian sederhana sepenuhnya gagal karena seluruh badan kode dibuang. PenjumlahanSystem.identityHashCode
(tidakString.hashCode
) menunjukkanStringBuffer
kode memiliki sedikit keuntungan. Dapat berubah ketika pembaruan berikutnya dirilis, atau jika Anda menggunakan JVM yang berbeda. Dari @lukaseder , daftar intrinsik HotSpot JVM .sumber
javap -c
pada kelas terkompilasi yang menggunakannya. (Oh, seperti dalam jawabannya. Anda hanya perlu menafsirkan pembongkaran bytecode, yang seharusnya tidak terlalu sulit.)StringBuilder
bahkan ketika bergabung dengan dua string? JikaString
menyertakan metode statis untuk menggabungkan hingga empat string, atau semua string dalamString[]
, kode dapat menambahkan hingga empat string dengan alokasi objek dua (hasilString
dan dukungannyachar[]
, tidak ada yang berlebihan), dan sejumlah string dengan alokasi tiga ( ituString[]
, hasilnyaString
, dan dukunganchar[]
, dengan hanya yang pertama yang berlebihan). Karena itu, menggunakanStringBuilder
kehendak terbaik membutuhkan empat alokasi, dan akan membutuhkan menyalin setiap karakter dua kali.Niyaz benar, tetapi perlu juga dicatat bahwa operator + khusus dapat dikonversi menjadi sesuatu yang lebih efisien oleh kompiler Java. Java memiliki kelas StringBuilder yang mewakili String yang tidak dapat diubah, aman, dapat diubah. Saat melakukan sekelompok rangkaian String, kompiler Java secara diam-diam mengonversi
ke
yang untuk string besar secara signifikan lebih efisien. Sejauh yang saya tahu, ini tidak terjadi ketika Anda menggunakan metode concat.
Namun, metode concat lebih efisien ketika menggabungkan String kosong ke String yang ada. Dalam hal ini, JVM tidak perlu membuat objek String baru dan cukup mengembalikan yang sudah ada. Lihat dokumentasi concat untuk mengonfirmasi hal ini.
Jadi, jika Anda sangat memperhatikan efisiensi maka Anda harus menggunakan metode concat saat menggabungkan string-string yang mungkin kosong, dan gunakan + sebaliknya. Namun, perbedaan kinerja harus diabaikan dan Anda mungkin tidak perlu khawatir tentang hal ini.
sumber
String
- seperti yang Anda katakan,concat
memiliki satu pengecualian saat Anda membuat kosongString
.Saya menjalankan tes serupa dengan @marcio tetapi dengan loop berikut sebagai gantinya:
Hanya untuk ukuran yang baik, saya juga melempar
StringBuilder.append()
. Setiap tes dijalankan 10 kali, dengan 100rb repetisi untuk setiap putaran. Inilah hasilnya:StringBuilder
menang telak. Hasil jam waktu adalah 0 untuk sebagian besar berjalan, dan yang paling lama mengambil 16ms.a += b
membutuhkan sekitar 40000 ms (40 detik) untuk setiap proses.concat
hanya membutuhkan 10000ms (10s) per run.Saya belum mendekompilasi kelas untuk melihat internal atau menjalankannya melalui profiler, tapi saya curiga
a += b
menghabiskan banyak waktu membuat objek baruStringBuilder
dan kemudian mengubahnya kembaliString
.sumber
+
digunakan untuk dua string, apakah ada kasus di mana menggunakanStringBuilder
lebih baik daripada yang akan terjadiString.valueOf(s1).concat(s2)
? Adakah gagasan mengapa kompiler tidak akan menggunakan yang terakhir [atau mengabaikanvalueOf
panggilan jikas1
tidak diketahui null]?Sebagian besar jawaban di sini berasal dari 2008. Tampaknya banyak hal telah berubah dari waktu ke waktu. Benchmark terbaru saya yang dibuat dengan JMH menunjukkan bahwa di Java 8
+
sekitar dua kali lebih cepat daripadaconcat
.Tolok ukur saya:
Hasil:
sumber
String
tidak pernah memasukkan fungsi statis untuk membentuk string dengan merangkai unsur-unsur aString[]
. Menggunakan+
untuk menggabungkan 8 string menggunakan fungsi seperti itu akan membutuhkan pembangunan dan kemudian ditinggalkanString[8]
, tetapi itu akan menjadi satu-satunya objek yang perlu dibangun ditinggalkan, sementara menggunakanStringBuilder
membutuhkan akan membangun dan meninggalkanStringBuilder
contoh dan setidaknya satuchar[]
toko dukungan.String.join()
metode statis ditambahkan di Java 8, seperti pembungkus sintaks cepat di sekitarjava.util.StringJoiner
kelas.+
diubah untuk menggunakan fungsi seperti itu?+
untuk menggunakannya) akan membutuhkan lebih dari apa yang ingin diubah oleh para dev Jawa.Tom benar dalam menggambarkan apa yang dilakukan operator +. Itu menciptakan sementara
StringBuilder
, menambahkan bagian-bagian, dan selesai dengantoString()
.Namun, semua jawaban sejauh ini mengabaikan efek dari optimasi runtime HotSpot. Secara khusus, operasi sementara ini diakui sebagai pola umum dan diganti dengan kode mesin yang lebih efisien saat dijalankan.
@marcio: Anda telah membuat tolok ukur mikro ; dengan JVM modern ini bukan cara yang valid untuk kode profil.
Alasan mengapa run-time optimasi penting adalah karena banyak perbedaan dalam kode ini - bahkan termasuk pembuatan objek - benar-benar berbeda ketika HotSpot berjalan. Satu-satunya cara untuk mengetahui dengan pasti adalah membuat profil kode Anda di tempat .
Akhirnya, semua metode ini sebenarnya sangat cepat. Ini mungkin merupakan kasus optimasi prematur. Jika Anda memiliki kode yang banyak merangkai string, cara untuk mendapatkan kecepatan maksimum mungkin tidak ada hubungannya dengan operator mana yang Anda pilih dan alih-alih algoritma yang Anda gunakan!
sumber
Bagaimana dengan beberapa pengujian sederhana? Gunakan kode di bawah ini:
"a + b"
Versi dieksekusi di 2500ms .a.concat(b)
dieksekusi di 1200ms .Diuji beberapa kali. The
concat()
eksekusi Versi mengambil setengah dari waktu rata-rata.Hasil ini mengejutkan saya karena
concat()
metode ini selalu menciptakan string baru (mengembalikan "new String(result)
". Sudah diketahui bahwa:Mengapa kompiler tidak dapat mengoptimalkan pembuatan string dalam kode "a + b", mengetahui bahwa selalu menghasilkan string yang sama? Itu bisa menghindari pembuatan string baru. Jika Anda tidak percaya dengan pernyataan di atas, ujilah diri Anda.
sumber
Pada dasarnya, ada dua perbedaan penting antara + dan
concat
metode.Jika Anda menggunakan metode concat maka Anda hanya akan dapat menggabungkan string sementara dalam kasus operator + , Anda juga dapat menggabungkan string dengan tipe data apa pun.
Sebagai contoh:
Dalam hal ini, outputnya harus 10Halo .
Dalam kasus di atas, Anda harus memberikan dua string wajib.
Perbedaan kedua dan utama antara + dan concat adalah:
Kasus 1: Misalkan saya menggabungkan string yang sama dengan operator concat dengan cara ini
Dalam hal ini jumlah objek yang dibuat dalam kumpulan adalah 7 seperti ini:
Kasus 2:
Sekarang saya akan menggabungkan string yang sama melalui operator +
Dalam kasus di atas, jumlah objek yang dibuat hanya 5.
Sebenarnya ketika kita meringkas string melalui + operator maka ia mempertahankan kelas StringBuffer untuk melakukan tugas yang sama sebagai berikut: -
Dengan cara ini hanya akan membuat lima objek.
Jadi ini adalah perbedaan mendasar antara + dan metode concat . Nikmati :)
sumber
String s="I"+"am"+"good"+"boy"; String s2 = "go".concat("od"); System.out.println(s2 == s2.intern());
cetakantrue
, yang berarti"good"
tidak ada di kolam string sebelum memanggilintern()
Demi kelengkapan, saya ingin menambahkan bahwa definisi operator '+' dapat ditemukan di JLS SE8 15.18.1 :
Tentang implementasi JLS mengatakan hal berikut:
Jadi menilai dari 'kompiler Java dapat menggunakan kelas StringBuffer atau teknik serupa untuk mengurangi', kompiler yang berbeda dapat menghasilkan byte-code yang berbeda.
sumber
The + Operator dapat bekerja antara string dan string, char, integer, double atau mengambang nilai tipe data. Itu hanya mengkonversi nilai ke representasi string sebelum penggabungan.
The Operator concat hanya dapat dilakukan dan dengan string. Ia memeriksa kompatibilitas tipe data dan membuat kesalahan, jika tidak cocok.
Kecuali ini, kode yang Anda berikan melakukan hal yang sama.
sumber
Saya kira tidak.
a.concat(b)
diimplementasikan dalam String dan saya pikir implementasi tidak banyak berubah sejak mesin java awal. The+
pelaksanaan operasi tergantung pada versi Jawa dan compiler. Saat+
ini diimplementasikan menggunakanStringBuffer
untuk membuat operasi secepat mungkin. Mungkin di masa depan, ini akan berubah. Dalam versi sebelumnya dari+
operasi java pada Strings jauh lebih lambat karena menghasilkan hasil antara.Saya kira itu
+=
diimplementasikan menggunakan+
dan dioptimalkan serupa.sumber
Saat menggunakan +, kecepatan berkurang seiring bertambahnya panjang string, tetapi saat menggunakan concat, kecepatannya lebih stabil, dan opsi terbaik adalah menggunakan kelas StringBuilder yang memiliki kecepatan stabil untuk melakukan itu.
Saya kira Anda bisa mengerti mengapa. Tetapi cara terbaik untuk membuat string panjang adalah menggunakan StringBuilder () dan append (), kecepatan keduanya tidak dapat diterima.
sumber