OK..看到公式就明白了..StringBuilder是以当前的Capacity*2来扩充的..所以,在使用StringBuilder需要特别注意,尤其是要拼接或追加N多字符的时候,要注意技巧的使用,可以适当的,有预见性的设置Capacity的值,避免造成过大内存的浪费,节约无谓的内存空间..例如,下列代码就可以根据情况自动的扩展,而避免了较大的内存浪费.
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拼接字符串的区别..你会吓到的!!
2 int i = 0 ;
3 long StartTime = DateTime.Now.Ticks;
4 while ( i < 100000 ) {
5sb.Append( i.ToString() );
6i++;
7}
8 long EndTime = DateTime.Now.Ticks;
9
10 Console.WriteLine( " 时间: " + ( EndTime - StartTime ) );
11
12 string sb1 = null ;
13 i = 0 ;
14 StartTime = DateTime.Now.Ticks;
15 while ( i < 100000 )
16 {
17sb1 += i;
18i++;
19}
20 EndTime = DateTime.Now.Ticks;
21 Console.WriteLine( " 时间: " + ( EndTime - StartTime ));
在上一篇进一步了解String 中,发现了string的不便之处,而string的替代解决方案就是StringBuilder的使用..它的使用也很简单System.Text.StringBuilder sb = new System.Text.StringBuilder();这样就初始化了一个StringBuilder ..之后我们可以通过Append()来追加字符串填充到sb中..在你初始化一个StringBuilder 之后,它会自动申请一个默认的StringBuilder 容量(默认值是16),这个容量是由Capacity来控制的.并且允许,我们根据需要来控制Capacity的大小,也可以通过Length来获取或设置StringBuilder 的长度..
先来看Length的用法:
通过上面的代码,我们可以看出如果StringBuilder 中的字符长度小于Length的值,则StringBuilder 将会用空格硬填充StringBuilder ,以满足符合长度的设置..如果StringBuilder 中的字符长度大于Length的值,则StringBuilder 将会截取从第一位开始的Length个字符..而忽略超出的部分..
再来看看最重要的部分Carpacity的用法:
2 sb.Append( " 123456789 " ); // 添加一个字符串
3 sb.Length = 3 ; // 设置容量为3
4 Console.WriteLine( sb.ToString() ); // 这里输出:123
5
6 sb.Length = 30 ; // 重新设置容量为30
7 Console.WriteLine( sb.ToString() + " ,结尾 " ); // 这里在原来字符串后面补齐空格,至到Length的为30
8 Console.WriteLine( sb.Length ); // 这里输出的长度为30
2 Console.Write( " Capacity: " + sb.Capacity ); // 这里的Capacity会自动扩大
3 Console.WriteLine( " /t Length: " + sb.Length );
4
5 sb.Append( ' 1 ' , 17 ); // 添加一个字符串,这里故意添加17个字符,是为了看到Capacity是如何被扩充的
6 Console.Write( " Capacity: " + sb.Capacity ); // 这里的Capacity会自动扩大
7 Console.WriteLine( " /t Length: " + sb.Length );
8
9 sb.Append( ' 2 ' , 32 ); // 添加一个字符串
10 Console.Write( " Capacity: " + sb.Capacity ); // 这里的Capacity会自动扩大
11 Console.WriteLine( " /t Length: " + sb.Length );
12
13 sb.Append( ' 3 ' , 64 ); // 添加一个字符串
14 Console.Write( " Capacity: " + sb.Capacity ); // 这里的Capacity会自动扩大
15 Console.WriteLine( " /t Length: " + sb.Length );
16
17 // 注意这里:如果你取消Remove这步操作,将会引发ArgumentOutOfRangeException异常,因为当前容量小于
18
19 //Length,这在自己控制StringBuilder的时候务必要注意容量溢出的问题
20
21 sb.Remove( 0 ,sb.Length); // 移出全部内容,再测试
22 sb.Capacity = 1 ; // 重新定义了容量
23 sb.Append( ' a ' , 2 );
24 Console.Write( " Capacity: " + sb.Capacity ); // 这里的Capacity会自动扩大
25 Console.WriteLine( " /t Length: " + sb.Length );
26
27 sb.Append( ' b ' , 4 );
28 Console.Write( " Capacity: " + sb.Capacity ); // 这里的Capacity会自动扩大
29 Console.WriteLine( " /t Length: " + sb.Length );
30
31 sb.Append( ' c ' , 6 );
32 Console.Write( " Capacity: " + sb.Capacity ); // 这里的Capacity会自动扩大
33 Console.WriteLine( " /t Length: " + sb.Length
上面的代码输出的结果:
2 Capacity: 32 Length: 17 // 第二次,我们故意添加了17个字符,于是Capacity=Capacity*2
3 Capacity: 64 Length: 49 // 继续超出,则Capacity=Capacity*2
4 Capacity: 128 Length: 113
5 Capacity: 3 Length: 2 // 清空内容后,设置Capacity=1,重新添加了字符
6 Capacity: 7 Length: 6 // 后面的结果都类似
7 Capacity: 14 Length: 12
从上面的代码和结果可以说明StringBuilder中容量Capacity是如何增加的:创建一个StringBuilder之后,默认的Capacity初始化为16,接着我们添加17个字符,以方便看到Capacity的扩充后的值..大家在修改Capacity的时候,一定要注意21行的注释,一定要确保Capacity >= Length,否则会引发ArgumentOutOfRangeException异常...看完结果,就可以推断出Capacity的公式:
if ( Capacity < Length && Capacity > 0 ){
Capacity *= 2;
}