2012-01-22 16 views
22

Có thể tôi tóc chẻ, nhưng tôi đã tự hỏi trong trường hợp sau đây:Tuy nhiên, một lần nữa vào chuỗi gắn vs concat vs +

String newString = a + b + c; //case 1 


String newString = a.concat(b).concat(c); //case 2 

StringBuilder newString = new StringBuilder(); //case 3 
newString.append(a); 
newString.append(b);  
newString.append(c); 

nào là tốt nhất để sử dụng không?

Ý tôi là tốt nhất trong theo bất kỳ cách nào.

Đọc về những, bài khác nói rằng trường hợp 3 không phải là hiệu suất tối ưu khôn ngoan, những người khác rằng trường hợp 1 sẽ kết thúc trong trường hợp 3, vv

Để cụ thể hơn.

Ví dụ: đặt tất cả sang một bên, kiểu nào phù hợp hơn để xem từ một lập trình viên khác nếu bạn phải duy trì mã của mình?

Hoặc bạn sẽ xem xét chương trình nào hiệu quả hơn?
Hoặc bạn sẽ nghĩ nhanh hơn, v.v.

Tôi không biết cách thể hiện điều này.

Câu trả lời như ví dụ: trường hợp 3 có thể nhanh hơn nhưng phần lớn các lập trình viên thích trường hợp 1 bởi vì nó là dễ đọc nhất cũng được chấp nhận nếu nó được xây dựng bằng cách nào đó tốt hơn

+2

Tôi không nhớ downvote.I nhớ rất nhiều downvote ẩn danh – Cratylus

+0

Câu hỏi này có lẽ là một dupe của một vài người khác. (Upvoted là không ai có liên quan đến một dupe.) –

+0

@Cratylus, Chúc tôi có thể upvote bình luận của bạn một lần nữa và một lần nữa. Nhưng những người quan tâm, SO không phải là SO mà không có downvotes ẩn danh. – 3bdalla

Trả lời

19

Trường hợp 1 là súc tích, thể hiện mục đích rõ ràng, và tương đương với trường hợp 3.

Trường hợp 2 kém hiệu quả hơn và cũng ít dễ đọc hơn.

Trường hợp 3 gần như hiệu quả như trường hợp 1, nhưng dài hơn và ít có thể đọc được hơn.

Trường hợp sử dụng 3 chỉ tốt hơn để sử dụng khi bạn phải ghép nối trong vòng lặp. Nếu không, trình biên dịch biên dịch case 1 thành case 3 (ngoại trừ nó xây dựng StringBuilder với new StringBuilder(a)), làm cho nó hiệu quả hơn trường hợp của bạn 3).

+2

+1: Trường hợp 2 tạo ra một đối tượng tạm thời, giống như các trường hợp khác, do đó, nó không rõ ràng đối với tôi ít hiệu quả hơn, nhưng đồng ý rằng nó ít có khả năng rõ ràng nhất. (Một phần vì ít phổ biến nhất để sử dụng) –

+0

Nó có 1 đối tượng tạm thời (thực tế là 2, nếu bạn đếm mảng char) vì chỉ có 3 chuỗi để nối. Nếu bạn thêm nhiều chuỗi hơn, bạn sẽ có thêm một đối tượng tạm thời trên mỗi chuỗi. –

+1

Đồng ý nó cũng không mở rộng quy mô. Đối với 'a.concat (b)' nó thực sự tốt hơn một chút. –

2

Trường hợp 3 tốt hơn trong hầu hết các khía cạnh. Trong trường hợp 3, bạn không kết thúc việc tạo 3 đối tượng chuỗi. Bởi vì chuỗi bất biến, 2 sẽ có phí tạo đối tượng chuỗi cho mỗi + (hoặc) concat.

EDIT: Đọc lại tài liệu và đồng ý với hầu hết các nhận xét, trường hợp 1 là case3.

+0

Và thường là khi bạn đang thực hiện thao tác văn bản ở nơi hiệu suất quan trọng, bạn đang làm việc với (a) khối lượng hoạt động lớn hơn nhiều; và (b) các hoạt động phức tạp hơn như tìm kiếm và chèn hoặc xóa văn bản. – user268396

+2

Các JVM hiện đại chuyển đổi trường hợp 1 thành trường hợp 3 trên thời gian chạy, do đó sẽ không có 3 đối tượng String. Nhưng nếu có rất nhiều nối tiếp tuần tự (trong các câu lệnh khác nhau) hoặc trong một vòng lặp, thì có mỗi câu lệnh tạo ra một chuỗi bất biến mới. –

+0

Cảm ơn Amir! đồng ý và cập nhật câu trả lời của tôi. – kosa

7

Trường hợp 3 là hình thức hiệu quả nhất, nhưng JVM chuyển đổi trường hợp từ 1 tới trường hợp 3.

Nhưng tôi tin rằng trường hợp 2 là điều tồi tệ nhất, nó không phải là có thể đọc được như trường hợp 1 và không phải là thực hiện như trường hợp 3

Nếu bạn muốn chuỗi trùng lặp trong vòng lặp chỉ dùng trường hợp 3, bạn có thể kiểm tra hiệu suất một cách dễ dàng, nhưng nếu nó không nằm trong vòng lặp (hoặc bạn không thêm nhiều chuỗi theo thứ tự) hầu như giống nhau.

Những trường hợp mà bạn sẽ không sử dụng toán tử + là:

String a = ""; 
for (String x : theStrings) { 
    a += x; 
} 

hoặc

String a = b + c; 
a = a + d; 
a = a + e; 
a = a + f; 
1

Đối với các trường hợp đơn giản, sử dụng + rõ ràng là dễ đọc hơn.

Đối với trường hợp hiếm gặp phức tạp hơn, StringBuilder có ý nghĩa. Nếu bạn đang chia tách trên các dòng, thì + có thể nhanh chóng là hiệu suất kéo. Các vòng lặp đi từ O (n) đến O (n^2) - không phải là vấn đề nếu n là nhỏ, nhưng một vấn đề lớn nếu n có thể lớn trong trường hợp khó xử (có thể khi làm điều gì đó quan trọng hoặc khi ai đó đang bị độc hại).

Trái với các câu trả lời khác, nếu bạn chỉ có ba chuỗi, concat có thể là người chiến thắng hiệu suất. Tôi có tinh thần không? Không. Hãy xem xét hai lựa chọn khác. Bạn đang tạo một đối tượng StringBuilder, với một mảng. Việc thêm các chuỗi cũng có thể yêu cầu mảng được thay thế và bạn có thể có các bit lẻ ở cuối mảng (của một chi tiết cụ thể để phân bổ, do đó, thêm một số char s có thể hoặc không thể tăng mức sử dụng bộ nhớ). Bạn có thể tính toán dung lượng cần thiết nếu bạn ghét mọi người đọc mã của bạn. Trường hợp tốt nhất, hai mảng (một cho StringBuilder, một cho số String (không chia sẻ trong tám năm qua)) mỗi kích thước của văn bản kết quả và hai đối tượng khác (StringBuilderString). Bây giờ cho concat bạn sẽ phân bổ cho String đối tượng có hai mảng, nhưng mảng đầu tiên sẽ ngắn hơn c.length(). Đó là một chiến thắng! Vâng, không phải cho dễ đọc.

Tuyên bố từ chối: JVM có thể thực hiện tối ưu hóa hoang dã, bao gồm phân bổ stack sau khi phân tích thoát và lớp vỏ đặc biệt của các lớp lõi. Họ có nhiều khả năng tối ưu hóa mã phổ biến và đơn giản hơn mã bị xáo trộn bằng tay.

Các vấn đề liên quan