2013-04-25 28 views
13

Tôi có một chuỗi rất lớn như sau:Sử dụng + để concat chuỗi trong Java

String str = "aaaaaaa" 
     + "bbbbbbbb" 
     + "cccccccc" 
    .... 

     + "zzzzzzzz"; // about 200 lines long 

Có một sự lãng phí lớn của bộ nhớ? Nó sẽ được tốt hơn để đặt nó trong một dòng hoặc sử dụng StringBuilder? Điều này được thực hiện để tạo một sql dài.

+6

Câu hỏi hay hơn là, tại sao bạn ghép nối nhiều dòng? – Makoto

+1

@Makoto Bạn sẽ làm như thế nào? – javaguy

+0

Vì bạn đang sử dụng nó với mục đích xây dựng các truy vấn SQL, tôi sẽ xem xét một API súc tích hơn để tạo ra, giống như [API tiêu chí] (http://docs.oracle.com/javaee/6/tutorial/ doc/gjitv.html). – Makoto

Trả lời

25

No. Trình biên dịch sẽ thực hiện việc ghép nối tại thời gian biên dịch nếu tất cả các chuỗi của bạn không đổi (như chúng có trong câu hỏi của bạn). Vì vậy, kết quả là thực hiện tốt hơn so với phiên bản StringBuilder.

Nó sẽ sử dụng StringBuilder (hoặc StringBuffer) để thực hiện kết nối của bất kỳ không liên tục các phần khác.

Vì vậy, các phiên bản biên dịch của:

String x = "a" + "b"; 

nên chính xác giống như:

String x = "ab"; 

Lưu ý rằng "không đổi" bộ phận có thể có nghĩa là đôi khi bạn có thể nhận được (rất nhỏ) hiệu quả thêm bằng cách sử dụng giá đỡ một cách khôn ngoan. Ví dụ:

int value = ...; 
String x = "a" + value + "b" + "c"; 

... là kém hiệu quả hơn:

int value = ...; 
String x = "a" + value + ("b" + "c"); 

... là người đầu tiên gắn "b""c" riêng. Phiên bản hiệu quả tương đương với:

int value = ...; 
String x = "a" + value + "bc"; 

Tôi không thể nhớ bao giờ thấy điều này được sử dụng như một vi-tối ưu hóa hợp pháp, nhưng nó ít nhất một địa điểm ưa thích.

+3

Không/không nên trình biên dịch thực hiện tối ưu hóa vi mô đó cho bạn sao? Hoặc, để nhìn vào nó từ một góc khác, có thể có bất kỳ giá trị 'foo' nào mà' (foo + "a") + "b" 'sẽ khác với' foo + "ab" '? –

+0

@IlmariKaronen: Không phải là tôi có thể nghĩ đến - nhưng đó là những gì tôi quan sát với javac tiêu chuẩn. Tôi nghĩ * nó sẽ là một tối ưu hóa hợp lệ mặc dù. –

+1

Có cách nào để không thực hiện tối ưu hóa không? – javaguy

2

No. Trình biên dịch sẽ tối ưu hóa điều này cho bạn thành một StringBuilder.

Chỉnh sửa: Như Louis Wasserman chỉ ra, nó cũng sẽ kết hợp các chuỗi ký tự cho bạn, do đó, câu lệnh trên sẽ chỉ là một chuỗi tại thời gian biên dịch.

+3

Không hoàn toàn chính xác. Nếu tất cả những chuỗi này là các chuỗi chữ, trình biên dịch sẽ chỉ tối ưu hóa nó thành một 'Chuỗi' duy nhất mà không sử dụng một' StringBuilder' chút nào. –

4

Trong các phiên bản Java hiện tại, mỗi thao tác + (ghép nối) được tự động biên dịch thành hoạt động StringBuilderappend(). Tuy nhiên, nếu nó nằm trong vòng lặp, nó sẽ tạo một StringBuilder mới cho mỗi lần lặp lại, phủ nhận hiệu ứng của nó - vì vậy, bạn nên quản lý rõ ràng hơn StringBuilder.

1

AFAIK JVM bên trong có một nhóm các chuỗi, mọi chuỗi bạn tạo được lưu trữ ở đó, loại bỏ các chuỗi cũ nhất/ít được sử dụng nhất (không chắc cách chọn nó). Nếu bạn explictly gọi String.intern() bạn đang nói với JVM để đặt String trong hồ bơi.

khi bạn nối hai chuỗi bằng cách sử dụng + bạn kết thúc bằng ba Chuỗi trong nhóm. Nếu bạn nối một + b + c, bạn woyld kết thúc bằng 5 Chuỗi (a, b, ab, c, abc)

Ít nhất đó là những gì tôi nhớ lại trên các phiên bản JVM cũ hơn, nhưng Luiggi có lẽ đúng, rằng trên những phiên bản mới hơn của nó trong nội bộ tối ưu hóa

1

mã:

String str = "aaaaaaa" + "bbbbbbbb" + "cccccccc"; 

được chuyển đổi tại thời gian biên dịch để:

String str = (new StringBuilder()).append("aaaaaaa").append("bbbbbbbb").append("cccccccc").toString(); 

Vì vậy, có vẻ không được bất kỳ sự khác biệt trong việc sử dụng StringBuilder.

Có một bài viết rất tốt đẹp mà so sánh chặt chẽ việc thực hiện các concat (+) so với StringBuilder và StringBuffer, hoàn chỉnh với đồ thị dòng:

StringBuilder vs StringBuffer vs String.concat - Done Right.