Praktik / kinerja terbaik: mencampur StringBuilder.append dengan String.concat

87

Saya mencoba untuk memahami apa praktik terbaik dan mengapa menggabungkan string literal dan variabel untuk kasus yang berbeda. Misalnya jika saya memiliki kode seperti ini

StringBuilder sb = new StringBuilder("AAAAAAAAAAAAA")
    .append(B_String).append("CCCCCCCCCCC").append(D_String)
    .append("EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE")
    .append("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF");

Apakah ini cara melakukannya? Dari posting ini , saya perhatikan bahwa +operator di Strings membuat instance baru dari StringBuilder, menggabungkan operan, dan mengembalikan konversi String, yang sepertinya lebih banyak bekerja daripada hanya memanggil .append(); jadi jika itu benar, maka itu tidak mungkin. Tapi bagaimana dengan String.concat()? Apakah tepat digunakan .append()untuk setiap penggabungan? Atau hanya untuk variabel, dan literal boleh ditambahkan .concat()?

StringBuilder sb = new StringBuilder("AAAAAAAAAAAAA")
    .append(B_String.concat("CCCCCCCCCCC")).append(D_String
    .concat("EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE")
    .concat("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"));

Apa aturan umum untuk praktik dan kinerja terbaik untuk menghadapi situasi ini? Apakah asumsi saya benar +dan seharusnya tidak digunakan?

Nick Rolando
sumber
Saya pikir pada dasarnya Anda sudah mendapatkannya. Ada beberapa pendapat berbeda mengenai apakah String + "sebaiknya tidak digunakan". Intinya adalah Anda memahami konsekuensinya
ControlAltDel

Jawaban:

185

+ operator

String s = s1 + s2

Di balik layar ini diterjemahkan ke:

String s = new StringBuilder(s1).append(s2).toString();

Bayangkan berapa banyak pekerjaan ekstra yang ditambahkannya jika Anda ada di s1 + s2sini:

stringBuilder.append(s1 + s2)

dari pada:

stringBuilder.append(s1).append(s2)

Beberapa string dengan +

Perlu dicatat bahwa:

String s = s1 + s2 + s3 + ... +sN

diterjemahkan ke:

String s = new StringBuilder(s1).append(s2).append(s3)...apend(sN).toString();

concat()

String s = s1.concat(s2);

Stringmembuat char[]larik yang bisa memuat s1dan s2. Salinan s1dan s2konten ke array baru ini. Sebenarnya membutuhkan lebih sedikit pekerjaan daripada +operator.

StringBuilder.append()

Mempertahankan char[]larik internal yang tumbuh saat dibutuhkan. Tidak ada tambahan char[]yang dibuat jika internal cukup besar.

stringBuilder.append(s1.concat(s2))

juga berkinerja buruk karena s1.concat(s2)membuat char[]larik tambahan dan menyalin s1dan s2hanya untuk menyalin konten larik baru itu ke internal StringBuilder char[].

Karena itu, Anda harus menggunakan append()sepanjang waktu dan menambahkan string mentah (cuplikan kode pertama Anda benar).

Tomasz Nurkiewicz
sumber
Terima kasih atas bantuan Anda, dan penjelasan yang mendalam; itulah yang saya butuhkan.
Nick Rolando
12
Meskipun versi terbaru dari kompilator secara otomatis mengoptimalkan operator + ke pembuat string, belum tentu merupakan hal yang baik untuk berasumsi bahwa versi yang lebih lama tidak. Ada topik yang sangat penting yang diabaikan dalam keseluruhan diskusi ini yang sebenarnya merupakan salah satu tujuan utama StringBuilder yang merupakan kumpulan string. Menggunakan pembangun string menyimpan semuanya sebagai char [] dan tidak membuat String perantara seperti yang dilakukan operator + sebelum pengoptimalan kompiler (digunakan hanya untuk melakukan concat). Menggunakan concat membuat objek String perantara yang di-cache tetapi tidak digunakan.
LINEMAN78
Jadi jika saya melakukan pernyataan satu kali (bukan beberapa pernyataan di satu metode) penggabungan pada beberapa string berbeda. Tidak apa-apa untuk menggunakan +objek String daripada membuat StringBuilderuntuk penggabungan satu kali ini, karena pada dasarnya akan melakukan hal yang sama?
Nick Rolando
1
Dan jika saya hanya ingin menggabungkan satu karakter, apakah lebih baik menggunakan .append ('\ n') daripada .append ("\ n")? Karena karakter adalah tipe primitif, dan String adalah Objek?
vrwim
3
Edisi Java 2-nd yang efektif : Menggunakan operator penggabungan string berulang kali untuk menggabungkan n string membutuhkan waktu kuadrat di n. Jadi apakah masih relevan?
gkiko
16

Penyusun mengoptimalkan + penggabungan.

Begitu

int a = 1;
String s = "Hello " + a;

diubah menjadi

new StringBuilder().append("Hello ").append(1).toString();

Ada topik bagus di sini yang menjelaskan mengapa Anda harus menggunakan operator +.

Andy Turner
sumber
3
Kompilator akan benar-benar mengoptimalkannya String s = "Hello World";karena Anda menggunakan literal.
ColinD
@ColinD: +1. Baru saja mengubah cuplikan saya.
3

Optimasi dilakukan secara otomatis oleh compiler.

Kompilator Java2 secara otomatis akan mengubah yang berikut ini:

String s = s1 + s2; 

untuk

String s = (new StringBuffer()).append(s1).append(s2).toString();

Diambil langsung dari Praktik Terbaik Java di situs web Oracles.

BoldAsLove
sumber
2

Anda harus selalu menggunakan append.

concatbuat String baru jadi seperti yang +saya pikirkan.

Jika Anda concatatau menggunakan +dengan 2 string terakhir, JVM dapat melakukan optimasi sehingga sama seperti melakukan append dalam kasus ini.

alain.janinm
sumber
1

Jika Anda menggabungkan dua String dengan tepat, gunakan String.concat (buat String baru dengan membuat array-karakter baru yang cocok dengan String dan menyalin kedua array karakter Strings ke dalamnya).

Jika Anda menggabungkan beberapa (lebih dari dua) String dalam satu baris, gunakan + atau StringBuilder.append, tidak masalah, karena kompilator mengubah + menjadi StringBuilder.append. Ini bagus untuk beberapa String karena mempertahankan satu array karakter yang tumbuh sesuai kebutuhan.

Jika Anda menggabungkan beberapa String ke beberapa baris, buat satu StringBuilder dan gunakan metode append. Pada akhirnya ketika Anda selesai menambahkan Strings ke StringBuilder gunakan metode .toString () - untuk membuat String darinya. Untuk menggabungkan dalam beberapa baris, ini lebih cepat daripada metode kedua, karena metode kedua akan membuat StringBuilder baru di setiap baris, menambahkan Strings dan kemudian melemparkan kembali ke String, sedangkan metode ketiga hanya menggunakan satu StringBuilder untuk semuanya.

Dakkaron
sumber
0

Gunakan +operator adalah praktik terbaik, juga sederhana dan mudah dibaca.

Bahasa Java menyediakan dukungan khusus untuk operator penggabungan string (+), dan untuk konversi objek lain menjadi string. Penggabungan string diimplementasikan melalui kelas StringBuilder (atau StringBuffer) dan metode penambahannya.

Dokumen resmi: https://docs.oracle.com/javase/8/docs/api/java/lang/String.html

Do Nhu Vy
sumber
0

dalam tingkat kode byte tidak ada perbedaan dan kami tidak mengorbankan efisiensi di sana. Dalam kasus mengeksekusi level kode byte, itu harus melalui metode overloading operator non-inline untuk + dengan memanggil append. kemudian pada level bahasa assembly (Java ditulis dalam C dan C menghasilkan assemblies yang mirip dengan assembly, akan ada tambahan register call untuk menyimpan + pemanggilan metode di stack dan akan ada tambahan push. (pada kenyataannya, cross-compiler dapat mengoptimalkan + operator panggilan, dalam hal ini membuatnya tidak berbeda dengan efisiensi.)

Merupakan praktik yang baik untuk memiliki satu cara untuk meningkatkan keterbacaan. :)

Shevon Silva
sumber
0

Saya pribadi lebih suka pemformat stringStrings.format() satu baris yang mudah dibaca dan sederhana .

String b = "B value";
String d = "D value";
String fullString = String.format("A %s C %s E F", b, d);
// Output: A B value C D value E F
T04435
sumber
0

Semua jawaban cukup bagus dan jelas. Tapi saya merasa eksplorasi seputar teknik penggabungan string lainnya juga akan membantu seperti - Guava Joiner, Streams, String.format, dll.

Untuk detail lengkap tentang performa setiap teknik penggabungan java-string-concatenation-which-way-is-best .

Singkatnya, kinerja penggabungan bervariasi dengan no. string untuk digabungkan. Misalnya - untuk menggabungkan 1-10 string, teknik ini bekerja paling baik - StringBuilder, StringBuffer dan Plus Operator. Dan untuk menggabungkan 100 string - Guava Joiner, pustaka stringsUtils apache juga berfungsi dengan baik.

Silakan buka blog di atas. Ini benar-benar menjelaskan efisiensi kinerja dengan sangat baik.

Terima kasih.

coderAJ
sumber