2009-12-03 13 views
16

Chúng tôi sẽ tạo một String trong Java theo cách sau:Có cách nào "nhanh nhất" để xây dựng chuỗi trong Java?

String foo = "123456";

Tuy nhiên, giảng viên của tôi đã khẳng định với tôi rằng hình thành một String bằng cách sử dụng phương pháp format, như vậy:

String foo = String.format("%s", 123456);

là nhanh hơn nhiều .

Ngoài ra, anh ấy nói rằng việc sử dụng lớp StringBuilder thậm chí còn nhanh hơn.

 
StringBuilder sb = new StringBuilder(); 
String foo = sb.append(String.format("%s", 123456)).toString(); 



Đó là phương pháp nhanh nhất để tạo một String, nếu có thậm chí là một?

Chúng không thể chính xác 100% vì tôi có thể không nhớ chúng đầy đủ.

+0

Câu hỏi hay, là hộp này có tự động không? Tôi biết rằng Integer foo = 1 chậm hơn Integer foo = Integer.valueOf (1); – Trick

+7

Là một sinh viên, nó sẽ là tuyệt vời nếu bạn có thể nghĩ ra một cách để kiểm tra lý thuyết của mình. Bạn có thể viết một lớp Java mà sẽ xây dựng 100000 chuỗi/stringbuffers vv và thời gian không? –

+13

Tôi sẽ nói với giáo sư của bạn rằng trong thế giới thực, lợi thế hiệu suất rất rất nhỏ có thể là rất lớn bởi khả năng đọc. Hơn nữa, mã nên luôn luôn được viết để làm việc đầu tiên, đơn giản và dễ dàng nhất có thể, và sau đó tối ưu hóa NẾU có một nhu cầu (mà thường không có). –

Trả lời

24

Nếu chỉ có một chuỗi sau đó:

String foo = "123456"; 

là nhanh nhất. Bạn sẽ nhận thấy rằng dòng String.format"%s%" được khai báo trong đó, vì vậy tôi không thấy cách giảng viên có thể nghĩ nhanh hơn. Ngoài ra, bạn đã có một cuộc gọi phương thức trên đầu trang của nó.

Tuy nhiên, nếu bạn đang tạo chuỗi theo thời gian, chẳng hạn như trong vòng lặp, thì bạn sẽ muốn sử dụng một StringBuilder. Nếu bạn chỉ sử dụng += thì bạn đang xây dựng một chuỗi thương hiệu mới mỗi lần dòng += được gọi. StringBuilder nhanh hơn nhiều vì nó chứa bộ đệm và nối thêm vào mỗi lần bạn gọi append.

+0

suy nghĩ của tôi chính xác. – pstanton

+1

Vâng, nếu bạn đang khai báo một chuỗi chữ, sau đó chỉ cần nhúng nó rõ ràng là cách nhanh nhất. Tôi đã có một ngôn ngữ lập trình ngôn ngữ một khi nói với lớp rằng Java không có con trỏ, vì vậy bạn không thể tạo ra những thứ như danh sách liên kết, ông nghĩ rằng tất cả các bộ sưu tập java đã được thực hiện trong C hoặc một cái gì đó. Tôi có một giảng viên khác nói rằng các trang web 'an toàn' là những trang web kết thúc bằng '.shtml' (thay vì bắt đầu bằng https) Đôi khi họ không biết họ đang nói gì về –

+2

Cộng với một vòng lặp chặt chẽ, bạn có thể tạo Số lượng lớn các chuỗi mỗi một lớn hơn một chút so với cuối cùng. Điều này cũng đúng trong C# (well. Net). Tôi cũng đồng ý với nhận xét của Eric Wendelin rằng bạn nên viết một bài kiểm tra để xem. Đừng nói với các bạn những ý kiến ​​của mọi người về teh interwebz khi bạn có thể chỉ cho anh ta chứng minh bằng chứng liệu anh ấy đúng hay sai. Tôi sẽ thực hiện một số trường hợp kiểm tra: tốc độ tạo một chuỗi thông qua mỗi phương thức, tốc độ để tạo nhiều vòng lặp, v.v. – jeffa00

8
String foo = "some string literal"; 

Chắc chắn là cách nhanh nhất để tạo chuỗi. Nó được nhúng trong tệp .class và là một bộ nhớ đơn giản để tìm kiếm.

Sử dụng String.format khi bạn không có gì để thực sự định dạng trông có vẻ xấu xí và có thể khiến các nhà phát triển cơ sở phải khóc.

Nếu chuỗi sẽ bị sửa đổi, thì StringBuilder là tốt nhất kể từ Stringsimmutable.

+14

Sử dụng String.format khi bạn không có gì để thực sự định dạng cũng có thể khiến các nhà phát triển cao cấp cũng khóc. – JasCav

4

Nếu chuỗi của bạn được biết tại thời gian biên dịch, sau đó sử dụng chữ là tốt nhất: String foo = "123456";.

Nếu chuỗi của bạn không được biết tại thời gian biên dịch và bao gồm một tập hợp các chuỗi nhỏ hơn, StringBuilder thường là cách để đi (nhưng hãy cẩn thận an toàn chủ đề!).

Sử dụng String foo = String.format("%s", 123456);có thể giảm kích thước .class của bạn và làm cho lớp tải nhanh hơn một chút, nhưng điều chỉnh bộ nhớ cực kỳ tích cực (cực)^^.

4

Trong ví dụ thứ hai của bạn, sử dụng:

String foo = String.format("%s", 123456); 

không mua cho bạn bất cứ điều gì; 123456 đã là một giá trị không đổi, vậy tại sao không chỉ gán foo = "123456"?Đối với các chuỗi liên tục, không có cách nào tốt hơn.

Nếu bạn đang tạo chuỗi từ nhiều phần được nối với nhau trong thời gian chạy, hãy sử dụng StringBuffer hoặc StringBuilder (trước đây là chuỗi an toàn).

3

Như đã được chỉ ra, nếu bạn chỉ xây dựng một chuỗi không có nối, chỉ cần sử dụng String.

Để ghép nối nhiều bit thành một chuỗi lớn, StringBuffer chậm hơn StringBuilder, nhưng StringBuffer được đồng bộ hóa. Nếu bạn không cần đồng bộ hóa, StringBuilder.

11

Toàn bộ cuộc thảo luận này là tranh luận. Vui lòng đọc bài viết này của Jeff, tức là, người đã tạo Stack Overflow.

The Sad Tragedy of Micro-Optimization Theater

Vui lòng tham khảo hướng dẫn của bạn để bài đăng này và yêu cầu anh ta dừng lại hủy hoại não/học sinh của cô của mình với thông tin vô dụng. Tối ưu hóa thuật toán là nơi mã của bạn sẽ sống hoặc chết, không phải với phương pháp bạn sử dụng để tạo chuỗi. Trong bất kỳ trường hợp nào, StringBuilder và String formatter phải thực thi MÃ ACTUAL với REAL MEMORY, nếu bạn chỉ xây dựng một chuỗi nó được đặt sang một bên trong suốt thời gian biên dịch và sẵn sàng để sử dụng khi bạn cần nó, về bản chất, nó có 0 run- chi phí thời gian, trong khi các tùy chọn khác có chi phí thực, vì mã thực sự cần được thực thi.

+1

Không quá cầu kỳ, nhưng tôi nghĩ bạn có ý nói rằng cuộc thảo luận là "tranh luận". Mặc dù nó là "câm" quá vì SO không có âm thanh ...;) – jasonh

+2

Hãy vi-tối ưu hóa bài đăng này! :) – Tim

+0

Cảm ơn bạn đã sửa lỗi chính tả. – Michael

1

Ví dụ đầu tiên bạn đưa ra là nhanh nhất và đơn giản nhất. Dùng nó.

Mỗi đoạn mã bạn thêm vào trong các ví dụ đó làm cho nó chậm hơn và khó đọc hơn nhiều.

tôi sẽ đề nghị ví dụ 2 là ít nhất 10-100x chậm hơn so với ví dụ 1 và ví dụ 3 là khoảng 2x chậm hơn so với ví dụ 2.

đã xử lý của bạn cung cấp bất kỳ biện minh cho nhận định này?

BTW: Ví dụ đầu tiên của bạn không xây dựng một chuỗi nào cả (đó là lý do tại sao nó nhanh nhất), nó chỉ đưa cho bạn một Chuỗi đang ngồi trong nhóm hằng số Chuỗi.

2

Bạn có chắc chắn 100% rằng huấn luyện viên đã không nói về một cái gì đó như:

String foo = "" + 123456; 

tôi thấy sinh viên của tôi làm điều đó loại điều "tất cả các thời gian" (một số ít sẽ làm điều đó mỗi học kỳ). Lý do họ làm điều đó là một số cuốn sách chỉ cho họ cách làm theo cách đó. Lắc đầu và nắm tay với những người viết sách lười biếng!

+0

Tôi nghĩ đó là phím tắt thành ngữ cho 'foo = String.valueOf (int_var)'. Tôi đoán có một số chi phí cho việc tạo ra (tham chiếu) chuỗi rỗng, nhưng bên cạnh điều này, có gì sai với nó? –

+0

Nó không phải là điều rõ ràng nhất để làm. Ngoài ra String.valueOf (int) gọi Integer.toString (int) (không phải là một yêu cầu, nhưng đó là những gì JDK làm). Nếu trình biên dịch làm điều đó thì nó sẽ chậm hơn, tùy thuộc vào môi trường, hơn là gọi Integer.toString (int). Integer.toString (int) là rõ ràng hơn, với tôi, hơn "" + int và rõ ràng hơn. – TofuBeer

14

Hơi tắt chủ đề, nhưng tôi ước rằng toàn bộ huyền thoại "không phải-sử dụng-cộng-nối-nối-chuỗi-trong-Java" sẽ biến mất. Mặc dù nó có thể đúng trong các phiên bản đầu của Java mà StringBuffer nhanh hơn và "+ là tà ác", nó chắc chắn là không đúng trong các JVM hiện đại đang quan tâm đến rất nhiều sự tối ưu.

Ví dụ: nhanh hơn?

String s = "abc" + "def"; 

hoặc

StringBuffer buf = new StringBuffer(); 
    buf.append("abc"); 
    buf.append("def"); 
    String s = buf.toString(); 

Câu trả lời là cựu. JVM nhận ra rằng đây là một chuỗi liên tục và thực sự sẽ đặt "abcdef" trong nhóm chuỗi, trong khi phiên bản "stringbuffer" tối ưu hóa sẽ gây ra một đối tượng StringBuffer thêm được xây dựng.

Một tối ưu hóa JVM là

String s = onestring + " concat " + anotherstring; 

đâu JVM sẽ làm việc ra những cách tốt nhất để concatenating sẽ. Trong JDK 5, điều này có nghĩa là một StringBuilder sẽ được sử dụng nội bộ và nó sẽ nhanh hơn sử dụng một bộ đệm chuỗi.

Nhưng khi câu trả lời khác đã nói, "123456" liên tục trong câu hỏi của bạn chắc chắn là cách nhanh nhất và giảng viên của bạn nên quay trở lại để trở thành một sinh viên :-)

Và vâng, tôi đã đủ buồn để xác minh điều này bằng cách xem mã Java bytecode ...

+0

Xem thêm Gyaan cho bình luận "Khá off-topic" của bạn. Trong một kịch bản khác, việc tạo các String bằng StringBuilder sẽ hiệu quả hơn. Nếu bạn đang nối các chuỗi khác nhau qua vòng lặp, thường là trường hợp như Chuỗi đơn giản = ""; cho (int counter = 0; counter <100000; counter ++) { đơn giản + = truy cập; } // Phiên bản đơn giản này mất khoảng 12 giây để hoàn thành. StringBuffer buffer = new StringBuffer(); cho (int counter = 0; counter <100000; counter ++) { buffer.append (bộ đệm); } // Điều này chỉ mất 14 ms! – mac

+0

Rất tiếc, tôi mới nhận ra rằng tôi đang nhấn mạnh câu trả lời part2 hoặc jasonh. – mac

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