Về cơ bản, sử dụng vòng lặp để lặp lại ArrayList
là tùy chọn duy nhất:
KHÔNG sử dụng mã này, tiếp tục đọc đến cuối câu trả lời này để xem tại sao nó không được mong muốn và thay vào đó nên sử dụng mã nào:
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);
Trong thực tế, việc nối chuỗi sẽ trở nên tốt đẹp, vì javac
trình biên dịch sẽ tối ưu hóa việc nối chuỗi như một chuỗi các append
thao tác trên StringBuilder
mọi cách. Đây là một phần của quá trình tháo gỡ mã byte khỏi for
vòng lặp từ chương trình trên:
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;
Có thể thấy, trình biên dịch tối ưu hóa vòng lặp đó bằng cách sử dụng một StringBuilder
, vì vậy hiệu suất không phải là một mối quan tâm lớn.
(OK, trong cái nhìn thứ hai, StringBuilder
nó đang được khởi tạo trên mỗi lần lặp của vòng lặp, vì vậy nó có thể không phải là mã byte hiệu quả nhất. Khởi tạo và sử dụng một tường minhStringBuilder
có thể mang lại hiệu suất tốt hơn.)
Trong thực tế, tôi nghĩ rằng có bất kỳ loại đầu ra nào (có thể là vào đĩa hoặc trên màn hình) sẽ có tốc độ chậm hơn so với việc phải lo lắng về hiệu suất của chuỗi nối.
Chỉnh sửa: Như đã chỉ ra trong các nhận xét, tối ưu hóa trình biên dịch ở trên thực sự đang tạo ra một phiên bản mới củaStringBuilder
mỗi lần lặp. (Điều mà tôi đã lưu ý trước đây.)
Kỹ thuật được tối ưu hóa nhất để sử dụng sẽ là phản hồi của Paul Tomblin , vì nó chỉ khởi tạo một StringBuilder
đối tượng duy nhất bên ngoàifor
vòng lặp.
Viết lại mã trên để:
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());
Sẽ chỉ khởi tạo StringBuilder
một lần bên ngoài vòng lặp và chỉ thực hiện hai cuộc gọi đến append
phương thức bên trong vòng lặp, như được chứng minh trong mã byte này (hiển thị khởi tạo StringBuilder
và vòng lặp):
// 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
Vì vậy, thực sự tối ưu hóa tay nên được thực hiện tốt hơn, vì bên trong for
vòng lặp ngắn hơn và không cần phải khởi tạo a StringBuilder
trên mỗi lần lặp.