StringBuilder的实现与技巧

在上一篇进一步了解String 中,发现了string的不便之处,而string的替代解决方案就是StringBuilder的使用..它的使用也很简单System.Text.StringBuilder sb = new System.Text.StringBuilder();这样就初始化了一个StringBuilder ..之后我们可以通过Append()来追加字符串填充到sb中..在你初始化一个StringBuilder 之后,它会自动申请一个默认的StringBuilder 容量(默认值是16),这个容量是由Capacity来控制的.并且允许,我们根据需要来控制Capacity的大小,也可以通过Length来获取或设置StringBuilder 的长度..
先来看Length的用法:

1 None.gif System.Text.StringBuilder sb  =   new  System.Text.StringBuilder();
2 None.gifsb.Append(  " 123456789 "  ); // 添加一个字符串
3 None.gif sb.Length  =   3 ; // 设置容量为3
4 None.gif Console.WriteLine( sb.ToString() ); // 这里输出:123
5 None.gif
6 None.gifsb.Length  =   30 ; // 重新设置容量为30
7 None.gif Console.WriteLine( sb.ToString()  +   " ,结尾 " ); // 这里在原来字符串后面补齐空格,至到Length的为30
8 None.gif Console.WriteLine( sb.Length ); // 这里输出的长度为30


通过上面的代码,我们可以看出如果StringBuilder 中的字符长度小于Length的值,则StringBuilder 将会用空格硬填充StringBuilder ,以满足符合长度的设置..如果StringBuilder 中的字符长度大于Length的值,则StringBuilder 将会截取从第一位开始的Length个字符..而忽略超出的部分..

再来看看最重要的部分Carpacity的用法:

 1 None.gif System.Text.StringBuilder sb  =   new  System.Text.StringBuilder(); // 初始化一个StringBuilder
 2 None.gif Console.Write(  " Capacity: "   +  sb.Capacity ); // 这里的Capacity会自动扩大
 3 None.gif Console.WriteLine(  " \t Length: "   +  sb.Length );
 4 None.gif
 5 None.gifsb.Append(  ' 1 ' , 17  ); // 添加一个字符串,这里故意添加17个字符,是为了看到Capacity是如何被扩充的
 6 None.gif Console.Write(  " Capacity: "   +  sb.Capacity ); // 这里的Capacity会自动扩大
 7 None.gif Console.WriteLine(  " \t Length: "   +  sb.Length );
 8 None.gif
 9 None.gifsb.Append(  ' 2 ' , 32  ); // 添加一个字符串
10 None.gif Console.Write(  " Capacity: "   +  sb.Capacity ); // 这里的Capacity会自动扩大
11 None.gif Console.WriteLine(  " \t Length: "   +  sb.Length );
12 None.gif
13 None.gifsb.Append(  ' 3 ' , 64  ); // 添加一个字符串
14 None.gif Console.Write(  " Capacity: "   +  sb.Capacity ); // 这里的Capacity会自动扩大
15 None.gif Console.WriteLine(  " \t Length: "   +  sb.Length );
16 None.gif
17 None.gif // 注意这里:如果你取消Remove这步操作,将会引发ArgumentOutOfRangeException异常,因为当前容量小于
18 None.gif
19 None.gif//Length,这在自己控制StringBuilder的时候务必要注意容量溢出的问题
20 None.gif
21 None.gifsb.Remove( 0 ,sb.Length); // 移出全部内容,再测试
22 None.gif sb.Capacity  =   1 ; // 重新定义了容量
23 None.gif sb.Append(  ' a ' , 2  );
24 None.gifConsole.Write(  " Capacity: "   +  sb.Capacity ); // 这里的Capacity会自动扩大
25 None.gif Console.WriteLine(  " \t Length: "   +  sb.Length );
26 None.gif
27 None.gifsb.Append(  ' b ' , 4  );
28 None.gifConsole.Write(  " Capacity: "   +  sb.Capacity ); // 这里的Capacity会自动扩大
29 None.gif Console.WriteLine(  " \t Length: "   +  sb.Length );
30 None.gif
31 None.gifsb.Append(  ' c ' , 6  );
32 None.gifConsole.Write(  " Capacity: "   +  sb.Capacity ); // 这里的Capacity会自动扩大
33 None.gif Console.WriteLine(  " \t Length: "   +  sb.Length

上面的代码输出的结果:
1 None.gif Capacity: 16      Length: 0      // 输出第一次,默认的Capacity是16
2 None.gif Capacity: 32      Length: 17      // 第二次,我们故意添加了17个字符,于是Capacity=Capacity*2
3 None.gif Capacity: 64      Length: 49      // 继续超出,则Capacity=Capacity*2
4 None.gif Capacity: 128      Length: 113
5 None.gifCapacity: 3      Length: 2      // 清空内容后,设置Capacity=1,重新添加了字符
6 None.gif Capacity: 7       Length: 6      // 后面的结果都类似
7 None.gif Capacity: 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的值,避免造成过大内存的浪费,节约无谓的内存空间..例如,下列代码就可以根据情况自动的扩展,而避免了较大的内存浪费.

 1 None.gif System.Text.StringBuilder sb  =   new  System.Text.StringBuilder();
 2 None.gif int  i  =   0 ;
 3 None.gif long  StartTime   =  DateTime.Now.Ticks;
 4 ExpandedBlockStart.gifContractedBlock.gif while  ( i  <   100000  )  dot.gif {
 5InBlock.gifsb.Append( i.ToString() );
 6InBlock.gifi++;
 7ExpandedBlockEnd.gif}

 8 None.gif long  EndTime   =  DateTime.Now.Ticks;
 9 None.gif
10 None.gifConsole.WriteLine(  " 时间: "   +  ( EndTime - StartTime )  +   " \t Capacity: " +  sb.Capacity  +   " \t Length: "  
11 None.gif
12 None.gif +  sb.Length);
13 None.gif
14 None.gifSystem.Text.StringBuilder sb1  =   new  System.Text.StringBuilder();
15 None.gif =   0 ;
16 None.gifStartTime   =  DateTime.Now.Ticks;
17 None.gif while  ( i  <   100000  ) 
18 ExpandedBlockStart.gifContractedBlock.gif dot.gif {
19InBlock.gifif ( sb1.Capacity <= sb1.Length )//先判断是否>Length
20InBlock.gifsb1.Capacity += 7;//这里一定要根据情况的增加容量,否则会有性能上的消耗
21InBlock.gifsb1.Append( i.ToString() );
22InBlock.gifi++;
23ExpandedBlockEnd.gif}

24 None.gifEndTime   =  DateTime.Now.Ticks;
25 None.gif
26 None.gifConsole.WriteLine(  " 时间: "   +  ( EndTime - StartTime )  +   " \t Capacity: " +  sb1.Capacity  +   " \t 
27 None.gif
28 None.gifLength: "  + sb1.Length);
需要特别说明的一点是,自动增加的容量,一定要根据实际预见的情况而改变,否则不但起不到优化的作用,反而会影响到程序的性能..


另外,如果有时间的话,可以测试一下下面的代码,用string和StringBuilder拼接字符串的区别..你会吓到的!!

 1 None.gif System.Text.StringBuilder sb  =   new  System.Text.StringBuilder();
 2 None.gif int  i  =   0 ;
 3 None.gif long  StartTime   =  DateTime.Now.Ticks;
 4 ExpandedBlockStart.gifContractedBlock.gif while  ( i  <   100000  )  dot.gif {
 5InBlock.gifsb.Append( i.ToString() );
 6InBlock.gifi++;
 7ExpandedBlockEnd.gif}
 8 None.gif long  EndTime   =  DateTime.Now.Ticks;
 9 None.gif
10 None.gifConsole.WriteLine(  " 时间: "   +  ( EndTime - StartTime ) );
11 None.gif
12 None.gif string  sb1  =   null ;
13 None.gif =   0 ;
14 None.gifStartTime   =  DateTime.Now.Ticks;
15 None.gif while  ( i  <   100000  ) 
16 ExpandedBlockStart.gifContractedBlock.gif dot.gif {
17InBlock.gifsb1 += i;
18InBlock.gifi++;
19ExpandedBlockEnd.gif}

20 None.gifEndTime   =  DateTime.Now.Ticks;
21 None.gifConsole.WriteLine(  " 时间: "   +  ( EndTime - StartTime ));



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值