Java StringBuffer 和StringBuilder
其實在上麵的文章中我已經闡述過了什麼是String,其實,String三姐妹中還有兩個非常豐滿的存在:StringBuffer老大姐和StringBuilder小妹妹.
首先,前麵我們說過String是不能被修改的,無論你如何對String進行賦值(+)都會在字符串常連池裏麵生成一個值.並且把這個值得地址引用給String變量,所以,隻要是玩String後麵添加東西,都是創建一個全新的JavaString對象.這樣,我們可以來做個實驗:
//本來
一開始是想計算五百次的String添加計算的,kanla9ishi天真了,那麼五萬次呢....
class StringTest {
public static void main(String[] args) {
//在這裏定義一個循環結構,循環五百萬次.我們開你一下耗時:
long start = System.currentTimeMillis();
int x = 50000;
String value = "";
for (int i = 0; i < x; i++) {
value += i;
}
long stop = System.currentTimeMillis();
System.out.println("String 總共耗時為: " + (stop - start)/1000+"秒");
}
}
輸出:
String 總共耗時為: 6秒
現在來看StringBUffderder的情況:注意時間單位
class StringBufferTest2{
public static void main(String[] args) {
long start = System.currentTimeMillis();
int w = 5000000;
StringBuffer stringBuffer = new StringBuffer();
for(int i = 0;i<w ;i++){
stringBuffer.append(i);
}
long stop = System.currentTimeMillis();
System.out.println("StringBuffer 總共耗時為: " + (stop - start)+"毫秒");
}
}
輸出:
StringBuffer 總共耗時為: 308毫秒
然後...
class StringBudilerTest2{
public static void main(String[] args) {
long start = System.currentTimeMillis();
int y = 5000000;
StringBuilder stringBuilder = new StringBuilder();
for(int i = 0;i<y ;i++){
stringBuilder.append(i);
}
long stop = System.currentTimeMillis();
System.out.println("StringBudiler: 總共耗時為: " + (stop - start)+"毫秒");
}
}
輸出:
.StringBudiler: 總共耗時為: 240毫秒
大家可以很明顯的看出來了是怎麼一回事.String循環五萬次,了6000毫秒,而Stringbuffer循環添加五百萬個隻用了300毫秒!!!當然Stringbuilder隻用了200毫秒.我的天,這是什麼情況?
其實,為什麼String三姐妹這件的差距這麼的,就在於我開篇所說的,對於String來說,沒錯往已有的字符串後麵追加內容,都是一個新的對對象,是對象就需要去給他開辟內存等等一些列複雜的炒作,但是,記住,但是@@@Stringbuffer和Stringbudiler在已有的字符串後麵追加,其實是在修應該這個已經存在了的String對象,而沒有創建新的對象!這既是為什麼有這麼大差距的原因了..是的,就是這樣的....
那麼...下一個問題.為什麼會有兩個高速修改字符類型的類?Stringbuffer和StringBudiler?
其實從上麵的數據也可以看出一點,Stringbuffer的速度沒有StrinhBuilder的速度快的,這是因為,StringBuffer是一個線程安全的類,你可以從他的源代碼看到他的所有方法第都添加了synchronized關鍵字來保證線程安全.而StringBuild沒有這種限製.如何選擇就得看你的業務覺得了.
最後一個問題.Stringbuffer和StringBudiler還有提升速度的空間嗎?
答案是有的.通過分析源代碼我們可以看到一個非常現實的東西,那就是,Sb們都有一個初始的容量.其值為16
class StringBufferAndStringBufiler{
public static void main(String[] args) {
StringBuffer stringBuffer = new StringBuffer();
int capacity = stringBuffer.capacity();
System.out.println("stringBuffer的初始容量: " + capacity);
StringBuilder stringBuilder = new StringBuilder();
int capacity1 = stringBuffer.capacity();
System.out.println("stringBuilder的初始容量: " + capacity1);
}
}
輸出:
stringBuffer的初始容量: 16
stringBuilder的初始容量: 16
容量是什麼?容量就是這個sb能裝多少的內容!這枚理解沒毛病的
class StringBufferAndStringBufiler{
public static void main(String[] args) {
StringBuffer stringBuffer = new StringBuffer("123");
int capacity = stringBuffer.capacity();
System.out.println("stringBuffer的現有容量: " + capacity);
StringBuilder stringBuilder = new StringBuilder("123");
int capacity1 = stringBuffer.capacity();
System.out.println("stringBuilder的現有容量: " + capacity1);
}
}
輸出:
stringBuffer的現有容量: 19
stringBuilder的現有容量: 19
以此可以看出,容量是可以改變的,那麼他是在什麼時候去改變你的呢?
看源代碼:
添加long新類型時:
public AbstractStringBuilder append(long l) {
if (l == Long.MIN_VALUE) {
append("-9223372036854775808");
return this;
}
int appendedLength = (l < 0) ? Long.stringSize(-l) + 1
: Long.stringSize(l);
int spaceNeeded = count + appendedLength;
ensureCapacityInternal(spaceNeeded);
Long.getChars(l, spaceNeeded, value);
count = spaceNeeded;
return this;
}
添
加```
inr類型時:
```javascript
public AbstractStringBuilder append(int i) {
if (i == Integer.MIN_VALUE) {
append("-2147483648");
return this;
}
int appendedLength = (i < 0) ? Integer.stringSize(-i) + 1
: Integer.stringSize(i);
int spaceNeeded = count + appendedLength;
ensureCapacityInternal(spaceNeeded);
Integer.getChars(i, spaceNeeded, value);
count = spaceNeeded;
return this;
}
從中都可以看到一個ensureCapacityInternal方法,該方法就是在檢查當前容量是否夠用.如果不夠則擴容.
了解這個對速度的提升有什麼幫助呢?
我們可以讓他不去做擴容,那麼相對的時間就可以減少了.這就要求我悶在初始化sb的時候要給一個大約的初始容量.比如:
class StringBufferTest2{
public static void main(String[] args) {
long start = System.currentTimeMillis();
int w = 5000000;
StringBuffer stringBuffer = new StringBuffer(1000000);//初始化stringBuffer的容量
for(int i = 0;i<w ;i++){
stringBuffer.append(i);
}
long stop = System.currentTimeMillis();
System.out.println("StringBuffer 總共耗時為: " + (stop - start)+"毫秒");
}
}
class StringBudilerTest2{
public static void main(String[] args) {
long start = System.currentTimeMillis();
int y = 5000000;
StringBuilder stringBuilder = new StringBuilder(10000000);//初始化stringBuilder的容量
for(int i = 0;i<y ;i++){
stringBuilder.append(i);
}
long stop = System.currentTimeMillis();
System.out.println("StringBudiler: 總共耗時為: " + (stop - start)+"毫秒");
}
}
對於這個值到底該是多少 ,當然就得靠你去估計一下咯.
至於sb們的一些方法,大家可以去看一下API其實和String沒有多少區別的.
好了,大家也看到了sb其實並不SB.
最後更新:2017-05-26 16:31:07