โดยพื้นฐานแล้วการใช้การวนซ้ำเพื่อวนซ้ำArrayList
เป็นตัวเลือกเดียว:
อย่าใช้รหัสนี้อ่านต่อไปที่ด้านล่างของคำตอบนี้เพื่อดูว่าทำไมมันจึงไม่เป็นที่ต้องการและควรใช้รหัสใดแทน:
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);
ในความเป็นจริงการต่อสตริงเป็นไปได้ดีเนื่องจากjavac
คอมไพเลอร์จะปรับการต่อสตริงให้เหมาะสมเป็นชุดของappend
การดำเนินการStringBuilder
ต่อไป นี่เป็นส่วนหนึ่งของการแยกส่วนของ bytecode จากfor
ลูปจากโปรแกรมด้านบน:
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;
ดังที่สามารถเห็นได้คอมไพเลอร์ปรับห่วงให้เหมาะสมโดยใช้ a StringBuilder
ดังนั้นประสิทธิภาพจึงไม่ควรเป็นเรื่องใหญ่
(ตกลงในทันทีที่สองStringBuilder
จะถูกสร้างอินสแตนซ์ในแต่ละรอบของการวนซ้ำดังนั้นมันอาจไม่ได้เป็น bytecode ที่มีประสิทธิภาพมากที่สุดการใช้อินสแตนซ์และการใช้อย่างชัดเจนStringBuilder
อาจทำให้ประสิทธิภาพดีขึ้น)
ในความเป็นจริงฉันคิดว่าการมีเอาต์พุตประเภทใด (ไม่ว่าจะเป็นดิสก์หรือหน้าจอ) อย่างน้อยจะมีลำดับความสำคัญช้ากว่าไม่ต้องกังวลเกี่ยวกับประสิทธิภาพของการต่อสตริง
แก้ไข:ตามที่ระบุไว้ในความคิดเห็นการเพิ่มประสิทธิภาพคอมไพเลอร์ข้างต้นเป็นการสร้างตัวอย่างใหม่ของStringBuilder
การทำซ้ำแต่ละครั้ง (ซึ่งฉันได้ระบุไว้ก่อนหน้านี้)
เทคนิคที่เหมาะสมที่สุดที่จะใช้คือการตอบสนองของPaul Tomblinเนื่องจากเป็นเพียงการยกตัวอย่างStringBuilder
วัตถุเดียวนอกfor
ลูป
เขียนใหม่เป็นรหัสด้านบนเพื่อ:
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());
จะสร้างอินสแตนซ์StringBuilder
นอกของลูปเพียงครั้งเดียวและทำการโทรทั้งสองไปยังappend
เมธอดภายในลูปตามที่ปรากฏในรหัสไบต์นี้ (ซึ่งแสดงการสร้างอินสแตนซ์ของStringBuilder
และลูป):
// 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
ดังนั้นการเพิ่มประสิทธิภาพของมือควรมีประสิทธิภาพดีกว่าเนื่องจากภายในของfor
ลูปนั้นสั้นกว่าและไม่จำเป็นต้องสร้างอินสแตนซ์ของการStringBuilder
วนซ้ำในแต่ละครั้ง