StringBuilder的實現與技巧
http://lixianhuei.cnblogs.com/archive/2005/12/27/305708.html
在上一篇進一步瞭解String 中,
發現了string的不便之處,而string的替代解決方案就是StringBuilder的使用..它的使用也很簡單
System.Text.StringBuilder sb = new
System.Text.StringBuilder();這樣就初始化了一個StringBuilder
..之後我們可以通過Append()來追加字符串填充到sb中..在你初始化一個StringBuilder
之後,它會自動申請一個默認的StringBuilder
容量(默認值是16),這個容量是由Capacity來控制的.並且允許,我們根據需要來控制Capacity的大小,也可以通過Length來獲取或設
置StringBuilder 的長度..
先來看Length的用法:
System.Text.StringBuilder sb = new System.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個字符..而忽略超出的部分.. 再來看看最重要的部分Carpacity的用法: System.Text.StringBuilder sb = new System.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 上面的代碼輸出的結果: 1Capacity:16 Length:0 //輸出第一次,默認的Capacity是16 2Capacity:32 Length:17 //第二次,我們故意添加了17個字符,於是Capacity=Capacity*2 3Capacity:64 Length:49 //繼續超出,則Capacity=Capacity*2 4Capacity:128 Length:113 5Capacity:3 Length:2 //清空內容後,設置Capacity=1,重新添加了字符 6Capacity:7 Length:6 //後面的結果都類似 7Capacity:14 Length:12 從 上面的代碼和結果可以說明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的值,避免造成過大內存的浪費,節約無謂的內存空間..例 如,下列代碼就可以根據情況自動的擴展,而避免了較大的內存浪費. 1System.Text.StringBuilder sb = new System.Text.StringBuilder(); 2int i = 0; 3long StartTime = DateTime.Now.Ticks; 4while ( i < 100000 ) { 5sb.Append( i.ToString() ); 6i++; 7} 8long EndTime = DateTime.Now.Ticks; 9 10Console.WriteLine( "時間:" + ( EndTime-StartTime ) + "\t Capacity:"+ sb.Capacity + "\t Length:" 11 12+ sb.Length); 13 14System.Text.StringBuilder sb1 = new System.Text.StringBuilder(); 15i = 0; 16StartTime = DateTime.Now.Ticks; 17while ( i < 100000 ) 18{ 19if ( sb1.Capacity <= sb1.Length )//先判斷是否>Length 20sb1.Capacity += 7;//這裏一定要根據情況的增加容量,否則會有性能上的消耗 21sb1.Append( i.ToString() ); 22i++; 23} 24EndTime = DateTime.Now.Ticks; 25 26Console.WriteLine( "時間:" + ( EndTime-StartTime ) + "\t Capacity:"+ sb1.Capacity + "\t 27 28Length:" + sb1.Length); 需要特別說明的一點是,自動增加的容量,一定要根據實際預見的情況而改變,否則不但起不到優化的作用,反而會影響到程序的性能.. 另外,如果有時間的話,可以測試一下下面的代碼,用string和StringBuilder拼接字符串的區別..你會嚇到的!!
1System.Text.StringBuilder sb = new System.Text.StringBuilder();
2int i = 0;
3long StartTime = DateTime.Now.Ticks;
4while ( i < 100000 ) {
5sb.Append( i.ToString() );
6i++;
7}
8long EndTime = DateTime.Now.Ticks;
9
10Console.WriteLine( "時間:" + ( EndTime-StartTime ) );
11
12string sb1 = null;
13i = 0;
14StartTime = DateTime.Now.Ticks;
15while ( i < 100000 )
16{
17sb1 += i;
18i++;
19}
20EndTime = DateTime.Now.Ticks;
21Console.WriteLine( "時間:" + ( EndTime-StartTime ));