String、StringBuffer、StringBuilder區(qū)別(java基礎(chǔ))

前言

本來是想自己整理的,在Google的時(shí)候,發(fā)現(xiàn)這篇已經(jīng)整理的挺完善了,通讀了一遍,頗有受益,轉(zhuǎn)過來記錄并分享一下??

1. String

String:字符串常量,字符串長度不可變。Java中String是immutable(不可變)的。

String類的包含如下定義:

/** The value is used for character storage. */
private final char value[];
 /** The offset is the first index of the storage that is used. */
private final int offset;
 /** The count is the number of characters in the String. */
private final int count;

用于存放字符的數(shù)組被聲明為final的,因此只能賦值一次,不可再更改。

2. StringBuffer(JDK1.0)

StringBuffer:字符串變量(Synchronized,即線程安全)。如果要頻繁對字符串內(nèi)容進(jìn)行修改,出于效率考慮最好使用StringBuffer,如果想轉(zhuǎn)成String類型,可以調(diào)用StringBuffer的toString()方法。

Java.lang.StringBuffer線程安全的可變字符序列。在任意時(shí)間點(diǎn)上它都包含某種特定的字符序列,但通過某些方法調(diào)用可以改變該序列的長度和內(nèi)容??蓪⒆址彌_區(qū)安全地用于多個(gè)線程。

StringBuffer 上的主要操作是 append 和 insert 方法,可重載這些方法,以接受任意類型的數(shù)據(jù)。每個(gè)方法都能有效地將給定的數(shù)據(jù)轉(zhuǎn)換成字符串,然后將該字符串的字符追加或插入到字符串緩沖區(qū)中。append 方法始終將這些字符添加到緩沖區(qū)的末端;而 insert 方法則在指定的點(diǎn)添加字符。例如,如果 z 引用一個(gè)當(dāng)前內(nèi)容是“start”的字符串緩沖區(qū)對象,則此方法調(diào)用 z.append("le") 會使字符串緩沖區(qū)包含“startle”,而 z.insert(4, "le") 將更改字符串緩沖區(qū),使之包含“starlet”。

3. StringBuilder(JDK5.0)

StringBuilder:字符串變量(非線程安全)。在內(nèi)部,StringBuilder對象被當(dāng)作是一個(gè)包含字符序列的變長數(shù)組。

java.lang.StringBuilder是一個(gè)可變的字符序列,是JDK5.0新增的。此類提供一個(gè)與 StringBuffer 兼容的 API,但不保證同步。該類被設(shè)計(jì)用作 StringBuffer 的一個(gè)簡易替換,用在字符串緩沖區(qū)被單個(gè)線程使用的時(shí)候(這種情況很普遍)。

其構(gòu)造方法如下:

| 構(gòu)造方法 | 描述 |
| StringBuilder() | 創(chuàng)建一個(gè)容量為16的StringBuilder對象(16個(gè)空元素) |
| StringBuilder(CharSequence cs) | 創(chuàng)建一個(gè)包含cs的StringBuilder對象,末尾附加16個(gè)空元素 |
| StringBuilder(int initCapacity) | 創(chuàng)建一個(gè)容量為initCapacity的StringBuilder對象 |
| StringBuilder(String s) | 創(chuàng)建一個(gè)包含s的StringBuilder對象,末尾附加16個(gè)空元素 |

在大部分情況下,StringBuilder > StringBuffer。這主要是由于前者不需要考慮線程安全。

4. 三者區(qū)別

String 類型和StringBuffer的主要性能區(qū)別:String是不可變的對象, 因此在每次對String 類型進(jìn)行改變的時(shí)候,都會生成一個(gè)新的 String 對象,然后將指針指向新的 String 對象,所以經(jīng)常改變內(nèi)容的字符串最好不要用 String ,因?yàn)槊看紊蓪ο蠖紩ο到y(tǒng)性能產(chǎn)生影響,特別當(dāng)內(nèi)存中無引用對象多了以后, JVM 的 GC 就會開始工作,性能就會降低。

使用 StringBuffer 類時(shí),每次都會對 StringBuffer 對象本身進(jìn)行操作,而不是生成新的對象并改變對象引用。所以多數(shù)情況下推薦使用 StringBuffer ,特別是字符串對象經(jīng)常改變的情況下。

在某些特別情況下, String 對象的字符串拼接其實(shí)是被 Java Compiler 編譯成了 StringBuffer 對象的拼接,所以這些時(shí)候 String 對象的速度并不會比 StringBuffer 對象慢,例如:

String s1 = “This is only a” + “ simple” + “ test”;
StringBuffer Sb = new StringBuilder(“This is only a”).append(“ simple”).append(“ test”);

生成 String s1對象的速度并不比 StringBuffer慢。其實(shí)在Java Compiler里,自動(dòng)做了如下轉(zhuǎn)換: Java Compiler 直接把上述第一條語句編譯為:

String s1 = “This is only a simple test”;

所以速度很快。但要注意的是,如果拼接的字符串來自另外的String對象的話,Java Compiler就不會自動(dòng)轉(zhuǎn)換了,速度也就沒那么快了,例如:

String s2 = “This is only a”;
String s3 = “ simple”;
String s4 = “ test”;
String s1 = s2 + s3 + s4;

這時(shí)候,Java Compiler會規(guī)規(guī)矩矩的按照原來的方式去做,String的concatenation(即+)操作利用了StringBuilder(或StringBuffer)的append方法實(shí)現(xiàn),此時(shí),對于上述情況,若s2,s3,s4采用String定義,拼接時(shí)需要額外創(chuàng)建一個(gè)StringBuffer(或StringBuilder),之后將StringBuffer轉(zhuǎn)換為String;若采用StringBuffer(或StringBuilder),則不需額外創(chuàng)建StringBuffer。

5. 使用策略

(1)基本原則:如果要操作少量的數(shù)據(jù),用String ;單線程操作大量數(shù)據(jù),用StringBuilder ;多線程操作大量數(shù)據(jù),用StringBuffer。

(2)不要使用String類的"+"來進(jìn)行頻繁的拼接,因?yàn)槟菢拥男阅軜O差的,應(yīng)該使用StringBuffer或StringBuilder類,這在Java的優(yōu)化上是一條比較重要的原則。例如:

String result = "";
for (String s : hugeArray) {    
result = result + s;
} 
// 使用StringBuilder
StringBuilder sb = new StringBuilder();
for (String s : hugeArray) {    
sb.append(s);
}
String result = sb.toString();

當(dāng)出現(xiàn)上面的情況時(shí),顯然我們要采用第二種方法,因?yàn)榈谝环N方法,每次循環(huán)都會創(chuàng)建一個(gè)String result用于保存結(jié)果,除此之外二者基本相同(對于jdk1.5及之后版本)。

(3)為了獲得更好的性能,在構(gòu)造 StringBuffer 或 StringBuilder 時(shí)應(yīng)盡可能指定它們的容量。當(dāng)然,如果你操作的字符串長度(length)不超過 16 個(gè)字符就不用了,當(dāng)不指定容量(capacity)時(shí)默認(rèn)構(gòu)造一個(gè)容量為16的對象。不指定容量會顯著降低性能。

(4)StringBuilder一般使用在方法內(nèi)部來完成類似"+"功能,因?yàn)槭蔷€程不安全的,所以用完以后可以丟棄。StringBuffer主要用在全局變量中。

(5)相同情況下使用 StringBuilder 相比使用 StringBuffer 僅能獲得 10%~15% 左右的性能提升,但卻要冒多線程不安全的風(fēng)險(xiǎn)。而在現(xiàn)實(shí)的模塊化編程中,負(fù)責(zé)某一模塊的程序員不一定能清晰地判斷該模塊是否會放入多線程的環(huán)境中運(yùn)行,因此:除非確定系統(tǒng)的瓶頸是在 StringBuffer 上,并且確定你的模塊不會運(yùn)行在多線程模式下,才可以采用StringBuilder;否則還是用StringBuffer。

轉(zhuǎn)載:
https://blog.csdn.net/kingzone_2008/article/details/9220691

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

友情鏈接更多精彩內(nèi)容