深入解析Java編程中的StringBuffer與StringBuider
String 的值是不可變的,每次對(duì)String的操作都會(huì)生成新的String對(duì)象,不僅效率低,而且耗費(fèi)大量?jī)?nèi)存空間。
StringBuffer類和String類一樣,也用來(lái)表示字符串,但是StringBuffer的內(nèi)部實(shí)現(xiàn)方式和String不同,在進(jìn)行字符串處理時(shí),不生成新的對(duì)象,在內(nèi)存使用上要優(yōu)于String。
StringBuffer 默認(rèn)分配16字節(jié)長(zhǎng)度的緩沖區(qū),當(dāng)字符串超過(guò)該大小時(shí),會(huì)自動(dòng)增加緩沖區(qū)長(zhǎng)度,而不是生成新的對(duì)象。
StringBuffer不像String,只能通過(guò) new 來(lái)創(chuàng)建對(duì)象,不支持簡(jiǎn)寫方式,例如:
StringBuffer str1 = new StringBuffer(); // 分配16個(gè)字節(jié)長(zhǎng)度的緩沖區(qū) StringBuffer str2 = =new StringBuffer(512); // 分配512個(gè)字節(jié)長(zhǎng)度的緩沖區(qū) // 在緩沖區(qū)中存放了字符串,并在后面預(yù)留了16個(gè)字節(jié)長(zhǎng)度的空緩沖區(qū) StringBuffer str3 = new StringBuffer(www.weixueyuan.net);
StringBuffer類的主要方法
StringBuffer類中的方法主要偏重于對(duì)于字符串的操作,例如追加、插入和刪除等,這個(gè)也是StringBuffer類和String類的主要區(qū)別。實(shí)際開(kāi)發(fā)中,如果需要對(duì)一個(gè)字符串進(jìn)行頻繁的修改,建議使用 StringBuffer。
1) append() 方法
append() 方法用于向當(dāng)前字符串的末尾追加內(nèi)容,類似于字符串的連接。調(diào)用該方法以后,StringBuffer對(duì)象的內(nèi)容也發(fā)生改變,例如:
StringBuffer str = new StringBuffer(“biancheng100”); str.append(true);
則對(duì)象str的值將變成”biancheng100true”。注意是str指向的內(nèi)容變了,不是str的指向變了。
字符串的”+“操作實(shí)際上也是先創(chuàng)建一個(gè)StringBuffer對(duì)象,然后調(diào)用append()方法將字符串片段拼接起來(lái),最后調(diào)用toString()方法轉(zhuǎn)換為字符串。
這樣看來(lái),String的連接操作就比StringBuffer多出了一些附加操作,效率上必然會(huì)打折扣。
但是,對(duì)于長(zhǎng)度較小的字符串,”+“操作更加直觀,更具可讀性,有些時(shí)候可以稍微犧牲一下效率。
2) deleteCharAt()
deleteCharAt() 方法用來(lái)刪除指定位置的字符,并將剩余的字符形成新的字符串。例如:
StringBuffer str = new StringBuffer("abcdef"); str. deleteCharAt(3);
該代碼將會(huì)刪除索引值為3的字符,即”d“字符。
你也可以通過(guò)delete()方法一次性刪除多個(gè)字符,例如:
StringBuffer str = new StringBuffer("abcdef"); str.delete(1, 4);
該代碼會(huì)刪除索引值為1~4之間的字符,包括索引值1,但不包括4。
3) insert() 方法
insert() 用來(lái)在指定位置插入字符串,可以認(rèn)為是append()的升級(jí)版。例如:
StringBuffer str = new StringBuffer("abcdef"); str.insert(3, "xyz");
最后str所指向的字符串為 abcdxyzef。
4) setCharAt() 方法
setCharAt() 方法用來(lái)修改指定位置的字符。例如:
StringBuffer str = new StringBuffer("abcdef"); str.setCharAt(3, 'z');
該代碼將把索引值為3的字符修改為 z,最后str所指向的字符串為 abczef。
以上僅僅是部分常用方法的簡(jiǎn)單說(shuō)明,更多方法和解釋請(qǐng)查閱API文檔。
String和StringBuffer的效率對(duì)比
為了更加明顯地看出它們的執(zhí)行效率,下面的代碼,將26個(gè)英文字母加了10000次。
public class Demo { public static void main(String[] args){ String fragment = "abcdefghijklmnopqrstuvwxyz"; int times = 10000; // 通過(guò)String對(duì)象 long timeStart1 = System.currentTimeMillis(); String str1 = ""; for (int i=0; i<times; i++) { str1 += fragment; } long timeEnd1 = System.currentTimeMillis(); System.out.println("String: " + (timeEnd1 - timeStart1) + "ms"); // 通過(guò)StringBuffer long timeStart2 = System.currentTimeMillis(); StringBuffer str2 = new StringBuffer(); for (int i=0; i<times; i++) { str2.append(fragment); } long timeEnd2 = System.currentTimeMillis(); System.out.println("StringBuffer: " + (timeEnd2 - timeStart2) + "ms"); } }
運(yùn)行結(jié)果:
String: 5287ms StringBuffer: 3ms
結(jié)論很明顯,StringBuffer的執(zhí)行效率比String快上千倍,這個(gè)差異隨著疊加次數(shù)的增加越來(lái)越明顯,當(dāng)疊加次數(shù)達(dá)到30000次的時(shí)候,運(yùn)行結(jié)果為:
String: 35923ms StringBuffer: 8ms
所以,強(qiáng)烈建議在涉及大量字符串操作時(shí)使用StringBuffer。
StringBuilder類
StringBuilder類和StringBuffer類功能基本相似,方法也差不多,主要區(qū)別在于StringBuffer類的方法是多線程安全的,而StringBuilder不是線程安全的,相比而言,StringBuilder類會(huì)略微快一點(diǎn)。
StringBuffer、StringBuilder、String中都實(shí)現(xiàn)了CharSequence接口。
CharSequence是一個(gè)定義字符串操作的接口,它只包括length()、charAt(int index)、subSequence(int start, int end) 這幾個(gè)API。
StringBuffer、StringBuilder、String對(duì)CharSequence接口的實(shí)現(xiàn)過(guò)程不一樣,如下圖所示:
可見(jiàn),String直接實(shí)現(xiàn)了CharSequence接口;StringBuilder 和 StringBuffer都是可變的字符序列,它們都繼承于AbstractStringBuilder,實(shí)現(xiàn)了CharSequence接口。
總結(jié)
線程安全:
StringBuffer:線程安全
StringBuilder:線程不安全
速度:
一般情況下,速度從快到慢為 StringBuilder > StringBuffer > String,當(dāng)然這是相對(duì)的,不是絕對(duì)的。
使用環(huán)境:
操作少量的數(shù)據(jù)使用 String;
單線程操作大量數(shù)據(jù)使用 StringBuilder;
多線程操作大量數(shù)據(jù)使用 StringBuffer。
相關(guān)文章
idea?http?request無(wú)法識(shí)別環(huán)境變量的解決步驟
AlibabaCloudToolkit插件安裝后在?Editor->File?Types增加?AlibabaCloudROStemplates(JSON)項(xiàng)且會(huì)配置為解析*.json?文件,導(dǎo)致http?client無(wú)法正確解析http-client.env.json文件而無(wú)法讀取環(huán)境變量,本文介紹idea?http?request無(wú)法識(shí)別環(huán)境變量問(wèn)題,需要的朋友可以參考下2023-08-08mybatis教程之查詢緩存(一級(jí)緩存二級(jí)緩存和整合ehcache)
這篇文章主要介紹了mybatis教程之查詢緩存(一級(jí)緩存二級(jí)緩存和整合ehcache),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-05-05springboot將mybatis升級(jí)為mybatis-plus的實(shí)現(xiàn)
之前項(xiàng)目工程用的是mybatis,現(xiàn)在需要將其替換為mybatis-plus,本文主要介紹了springboot將mybatis升級(jí)為mybatis-plus的實(shí)現(xiàn),具有一定的參考價(jià)值,感興趣的可以了解一下2023-09-09Java實(shí)戰(zhàn)之電影在線觀看系統(tǒng)的實(shí)現(xiàn)
這篇文章主要介紹了如何利用Java實(shí)現(xiàn)電影在線觀看系統(tǒng),文中用到的技術(shù)有:JSP、Spring、SpringMVC、MyBatis等,感興趣的可以了解一下2022-04-04SpringBoot項(xiàng)目在啟動(dòng)后自動(dòng)關(guān)閉的實(shí)現(xiàn)
我們?cè)趯憇pring?boot?web項(xiàng)目時(shí),有時(shí)會(huì)遇到啟動(dòng)后立即關(guān)閉的情況,?本文主要介紹了SpringBoot項(xiàng)目在啟動(dòng)后自動(dòng)關(guān)閉的實(shí)現(xiàn),具有一定的參考價(jià)值,感興趣的可以了解一下2024-01-01Java時(shí)間轉(zhuǎn)換成unix時(shí)間戳的方法
這篇文章主要為大家詳細(xì)介紹了Java時(shí)間轉(zhuǎn)換成unix時(shí)間戳的方法,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-12-12