2012-03-28 38 views
2

我在一個Java的書,上面寫着寫着:Java的解釋:爲什麼字符串不可改變使StringBuffer的更有效

因爲String是不可改變的,使用StringBuffer是更有效的。

我知道String實例是不可變的。

我也明白StringBuffer使處理字符串比正常更高效。

但我不能制定出的東西是什麼這兩個概念連接,即如何做String是不可改變的幫助StringBuffer

謝謝:)

+2

不可變使字符串變慢。因此,StringBuffer成爲一個更好的選擇。兩者之間不應該有直接的聯繫。 – 2012-03-28 03:25:38

+0

從2004年Java 5.0中的StringBuffer的Javadoc'從發佈JDK 5開始,這個類已經補充了一個爲單個線程StringBuilder設計的等價類。由於StringBuilder類支持所有相同的操作,所以通常應優先使用StringBuilder類,但速度更快,因爲它不執行同步。 '如果你關心性能,不要使用StringBuffer。 – 2012-03-28 07:13:11

+1

@AmitBhargava - 不可變字符串對於某些事物而言速度較慢,但​​對其他事物則較快。例如,substring(帶有可用的語義)通常比String是可變的更快,因爲不需要複製字符。但我同意**整體**,不變性使字符串變慢(可能)。 – 2012-04-05 04:22:11

回答

1

但我不能解決的是連接這兩個概念的東西,即如何使字符串不可變幫助StringBuffer?

它沒有。我認爲你只是曲解了你所引用的句子。

「因爲字符串是不可變的,所以使用StringBuffer更高效。」

這是說,StringBuffer是一個相對更有效的選項(對於某些任務)。換句話說:「因爲String是不可變的,所以使用StringBuffer比[爲某些任務使用String]更高效。」

這並不是說StringBuffer的絕對速度比如果String不是不可變的速度快。當然,這不是我讀報價的方式......也不是真實的說法。

8

因爲字符串是不可改變的,操作字符串,如連接字符串,則必須創建新的String對象,因爲很明顯,你不能改變現有的String對象的狀態。而用一個StringBuffer或StringBuilder的,您可以創建一個對象和簡單地改變其狀態。例如,如果您在for循環中執行一些主要的字符串連接,則此對象創建可能會非常昂貴。這就是說,我在這裏看到很多關於不涉及大規模連接的簡單字符串串聯的帖子,在這種情況下,使用StringBuffer或StringBuilder是一個過早和不必要的優化的例子。

另外請注意,您應該優先使用StringBuilder而不是StringBuffer,除非您的應用程序需要訪問多個線程中的對象,並且不介意這會產生額外的開銷。

+1

哦。這意味着:如果我想連接字符串「abc」和「def」但不使用緩衝區。在字符串池中將有:「abc」「abcd」「abcde」「abcdef」。但是如果使用緩衝區,只需要「abc」,「abcdef」,「def」。對 ? – hqt 2012-03-28 03:28:17

+0

不正確。首先,你的例子是微不足道的,並建議使用字符串是最好的方法。只需使用字符串,該池就會具有「abc」,「def」和「abcdef」。 – 2012-03-28 03:31:57

+1

@hqt - 不,只會有abc,def和abcdef。但是想象一下在一個循環中連接10個或更多的字符串 - 然後你會爲每個並置獲得一個新的字符串。另一方面,編譯器會優化它的位置。例如,文字'「abc」+「def」'在編譯時連接在一起,而不是運行時。如果你在一個語句中執行多個運行時連接,它將會創建一個StringBuilder並進行追加 - 就像你自己使用StringBuilder手動編寫一樣。請參閱http://stackoverflow.com/questions/1532461。 – 2012-03-28 03:36:44

2

這意味着什麼,因爲String是不可變的,所以最好使用StringBuffer(或StringBuilder)進行字符串操作,因爲每次更改基礎字符串時都不會創建新對象。

+1

哦。這意味着:如果我想連接字符串「abc」和「def」但不使用緩衝區。在字符串池中將有:「abc」「abcd」「abcde」「abcdef」。但是如果使用緩衝區,只需要「abc」,「abcdef」,「def」。對 ? – hqt 2012-03-28 03:32:52

1

所有其他職位肯定回答的問題。我想補充一點,你應該總是選擇StringBuilder而不是StringBufferStringBuffer具有內置線程同步功能,這是您幾乎永遠不需要的大量鎖定開銷。 StringBuilder沒有這個,因此速度更快。

其實即使你想要線程安全,這裏有some very good reasons也不要用StringBuffer

0

一成不變的概念可以很容易地用這個例子來說明

String s1 = "Hello"; 
String s2 = "Hi"; 
String s3 = "Hello"; 

if (s1 == s2){ System.out.println("s1==s2");} 
if (s1 == s3){ System.out.println("s1==s3");} 

s1 = "Hi"; 

if (s1 == s2){ System.out.println("s1==s2");} 
if (s1 == s3){ System.out.println("s1==s3");} 

如果執行這段代碼,你會得到 s1==s3s1==s2。這個例子解釋了什麼?

當您創建s1時,編譯器在其字符串表中創建了一個字符串「Hello」(我記得它的確切名稱)。當你創建s2時,它會創建新的對象「Hi」。現在當你創建s3時,編譯器知道它的字符串表中已經有一個對象「Hello」,所以爲什麼不把它引用到s3中。所以s1 = s3(記憶虎鉗)。同樣的事情發生在你指定的值「嗨」到S1,編譯器可以看到,「喜」已經在內存中指向的S3,所以它指出它S1爲好。

在StringBuffer的情況下,編譯器將內存分配給對象,您可以像處理字符串時那樣操作「池」。

相關問題