Pada dasarnya, menggunakan loop untuk beralih di atas ArrayList
adalah satu-satunya pilihan:
JANGAN gunakan kode ini, lanjutkan membaca di bagian bawah jawaban ini untuk melihat mengapa itu tidak diinginkan, dan kode mana yang harus digunakan sebagai gantinya:
ArrayList<String> list = new ArrayList<String>();
list.add("one");
list.add("two");
list.add("three");
String listString = "";
for (String s : list)
{
listString += s + "\t";
}
System.out.println(listString);
Bahkan, rangkaian string akan baik-baik saja, karena javac
kompiler akan mengoptimalkan rangkaian string sebagai serangkaian append
operasi pada StringBuilder
pokoknya. Berikut adalah bagian dari pembongkaran bytecode dari for
loop dari program di atas:
61: new #13; //class java/lang/StringBuilder
64: dup
65: invokespecial #14; //Method java/lang/StringBuilder."<init>":()V
68: aload_2
69: invokevirtual #15; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
72: aload 4
74: invokevirtual #15; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
77: ldc #16; //String \t
79: invokevirtual #15; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
82: invokevirtual #17; //Method java/lang/StringBuilder.toString:()Ljava/lang/String;
Seperti yang dapat dilihat, kompiler mengoptimalkan loop itu dengan menggunakan StringBuilder
, jadi kinerja seharusnya tidak menjadi perhatian besar.
(OK, pada pandangan kedua, StringBuilder
sedang dipakai pada setiap iterasi dari loop, jadi itu mungkin bukan bytecode paling efisien. Instantiating dan menggunakan eksplisit StringBuilder
mungkin akan menghasilkan kinerja yang lebih baik.)
Bahkan, saya berpikir bahwa memiliki segala jenis output (baik itu ke disk atau ke layar) akan setidaknya urutan besarnya lebih lambat daripada harus khawatir tentang kinerja rangkaian string.
Sunting: Seperti yang ditunjukkan dalam komentar, optimisasi kompiler di atas memang membuat contoh baru StringBuilder
pada setiap iterasi. (Yang telah saya catat sebelumnya.)
Teknik yang paling optimal untuk digunakan akan menjadi respons oleh Paul Tomblin , karena hanya instantiate satu StringBuilder
objek di luar for
loop.
Menulis ulang kode di atas ke:
ArrayList<String> list = new ArrayList<String>();
list.add("one");
list.add("two");
list.add("three");
StringBuilder sb = new StringBuilder();
for (String s : list)
{
sb.append(s);
sb.append("\t");
}
System.out.println(sb.toString());
Hanya akan membuat instantiate di StringBuilder
luar loop, dan hanya membuat dua panggilan ke append
metode di dalam loop, seperti dibuktikan dalam bytecode ini (yang menunjukkan instantiation StringBuilder
dan loop):
// Instantiation of the StringBuilder outside loop:
33: new #8; //class java/lang/StringBuilder
36: dup
37: invokespecial #9; //Method java/lang/StringBuilder."<init>":()V
40: astore_2
// [snip a few lines for initializing the loop]
// Loading the StringBuilder inside the loop, then append:
66: aload_2
67: aload 4
69: invokevirtual #14; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
72: pop
73: aload_2
74: ldc #15; //String \t
76: invokevirtual #14; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
79: pop
Jadi, memang optimasi tangan harus berkinerja lebih baik, karena bagian dalam for
loop lebih pendek dan tidak perlu instantiate StringBuilder
pada setiap iterasi.