StringBuilder的實現與技巧(轉)


1.Length

 

0.說明

在上一篇進一步了解String 中,發現了string的不便之處,而string的替代解決方案就是StringBuilder的使用
它的使用也很簡單
System.Text.StringBuilder sb =newSystem.Text.StringBuilder();
這樣就初始化了一個StringBuilder, 之后我們可以通過Append()來追加字符串填充到sb中
初始化StringBuilder 后,它會自動申請一個默認的StringBuilder 容量(默認值是16),
這個容量是由Capacity來控制的.並且允許,我們根據需要來控制Capacity的大小,也可以通過Length來獲取或設置StringBuilder 的長度

1.Length的用法

 

System.Text.StringBuilder sb =newSystem.Text.StringBuilder();
sb.Append("123456789");//添加一個字符串
sb.Length=3;//設置容量為3
Console.WriteLine( sb.ToString());//這里輸出:123
sb.Length=30;//重新設置容量為30
Console.WriteLine( sb.ToString()+",結尾");//這里在原來字符串后面補齊空格,至到Length的為30
Console.WriteLine( sb.Length);//這里輸出的長度為30

 

通過上面的代碼,我們可以看出如果StringBuilder 中的字符長度小於Length的值,則StringBuilder 將會用空格硬填充StringBuilder ,以滿足符合長度的設置
如果StringBuilder 中的字符長度大於Length的值,則StringBuilder 將會截取從第一位開始的Length個字符,而忽略超出的部分..
 

2.Capacity

 

1.代碼

System.Text.StringBuilder sb =newSystem.Text.StringBuilder();//初始化一個StringBuilder
Console.Write("Capacity:"+ sb.Capacity);//這里的Capacity會自動擴大
Console.WriteLine("\t Length:"+ sb.Length);
sb.Append('1',17);//添加一個字符串,這里故意添加17個字符,是為了看到Capacity是如何被擴充的
Console.Write("Capacity:"+ sb.Capacity);//這里的Capacity會自動擴大
Console.WriteLine("\t Length:"+ sb.Length);
sb.Append('2',32);//添加一個字符串
Console.Write("Capacity:"+ sb.Capacity);//這里的Capacity會自動擴大
Console.WriteLine("\t Length:"+ sb.Length);
sb.Append('3',64);//添加一個字符串
Console.Write("Capacity:"+ sb.Capacity);//這里的Capacity會自動擴大
Console.WriteLine("\t Length:"+ sb.Length);
//注意這里:如果你取消Remove這步操作,將會引發ArgumentOutOfRangeException異常,因為當前容量小於
//Length,這在自己控制StringBuilder的時候務必要注意容量溢出的問題
sb.Remove(0,sb.Length);//移出全部內容,再測試
sb.Capacity=1;//重新定義了容量
sb.Append('a',2);
Console.Write("Capacity:"+ sb.Capacity);//這里的Capacity會自動擴大
Console.WriteLine("\t Length:"+ sb.Length);
sb.Append('b',4);
Console.Write("Capacity:"+ sb.Capacity);//這里的Capacity會自動擴大
Console.WriteLine("\t Length:"+ sb.Length);
sb.Append('c',6);
Console.Write("Capacity:"+ sb.Capacity);//這里的Capacity會自動擴大
Console.WriteLine("\t Length:"+ sb.Length

2.輸出結果

Capacity:16Length:0//輸出第一次,默認的Capacity是16
Capacity:32Length:17//第二次,我們故意添加了17個字符,於是Capacity=Capacity*2
Capacity:64Length:49//繼續超出,則Capacity=Capacity*2
Capacity:128Length:113
Capacity:3Length:2//清空內容后,設置Capacity=1,重新添加了字符
Capacity:7Length:6//后面的結果都類似
Capacity:14Length:12

3.說明

從上面的代碼和結果可以說明StringBuilder中容量Capacity是如何增加的:
創建一個StringBuilder之后,默認的Capacity初始化為16,接着我們添加17個字符,以方便看到Capacity的擴充后的值
大家在修改Capacity的時候,一定要注意21行的注釋,一定要確保Capacity >= Length,否則會引發ArgumentOutOfRangeException異常.
看完結果,就可以推斷出Capacity的公式:
if ( Capacity < Length && Capacity > 0 ){
      Capacity *= 2;
}

OK..看到公式就明白了..StringBuilder是以當前的Capacity*2來擴充的
所以,在使用StringBuilder需要特別注意,尤其是要拼接或追加N多字符的時候,要注意技巧的使用
可以適當的,有預見性的設置Capacity的值,避免造成過大內存的浪費,節約無謂的內存空間
例如,下列代碼就可以根據情況自動的擴展,而避免了較大的內存浪費.
System.Text.StringBuilder sb =newSystem.Text.StringBuilder();
int i =0;
longStartTime=DateTime.Now.Ticks;
while( i <100000)
{
sb.Append( i.ToString());
i++;
}
longEndTime=DateTime.Now.Ticks;
Console.WriteLine("時間:"+(EndTime-StartTime)+"\t Capacity:"+ sb.Capacity+"\t Length:"
+ sb.Length);
System.Text.StringBuilder sb1 =newSystem.Text.StringBuilder();
i =0;
StartTime=DateTime.Now.Ticks;
while( i <100000)
{
if( sb1.Capacity<= sb1.Length)//先判斷是否>Length
{
sb1.Capacity+=7;//這里一定要根據情況的增加容量,否則會有性能上的消耗
}
sb1.Append( i.ToString());
i++;
}
EndTime=DateTime.Now.Ticks;
Console.WriteLine("時間:"+(EndTime-StartTime)+"\t Capacity:"+ sb1.Capacity+"\t
Length:" + sb1.Length);
 
需要特別說明的一點是,自動增加的容量,一定要根據實際預見的情況而改變,否則不但起不到優化的作用,反而會影響到程序的性能..

3.StringBuilder.Append 與 string+的性能比較

 

0.說明

一旦你的string在堆中創建后,其在內存中都是以const存在,任何的修改都會使其被重新創建為新的string,而指向以前的string的引用將會指向這個新的string!!
即每次string+操作,總會創建新的string,使得此操作占用內存空間大,耗時長。

1.代碼

System.Text.StringBuilder sb =newSystem.Text.StringBuilder();
int i =0;
longStartTime=DateTime.Now.Ticks;
while( i <100000) 
{
    sb.Append( i.ToString());
    i++;
}
longEndTime=DateTime.Now.Ticks;
Console.WriteLine("時間:"+(EndTime-StartTime));
string sb1 =null;
i =0;
StartTime=DateTime.Now.Ticks;
while( i <100000)
{
    sb1 += i;
    i++;
}
EndTime=DateTime.Now.Ticks;
Console.WriteLine("時間:"+(EndTime-StartTime));
本人實測時間
StringBuilder時間:      119964
string+時間:             410746739

2.總結

連接少量字符串:使用string
連接大量字符串:使用StringBuilder並注意對Capacity的控制

 




免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM