• 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("	 Length:"+ sb.Length);
    sb.Append('1',17);//添加一个字符串,这里故意添加17个字符,是为了看到Capacity是如何被扩充的
    Console.Write("Capacity:"+ sb.Capacity);//这里的Capacity会自动扩大
    Console.WriteLine("	 Length:"+ sb.Length);
    sb.Append('2',32);//添加一个字符串
    Console.Write("Capacity:"+ sb.Capacity);//这里的Capacity会自动扩大
    Console.WriteLine("	 Length:"+ sb.Length);
    sb.Append('3',64);//添加一个字符串
    Console.Write("Capacity:"+ sb.Capacity);//这里的Capacity会自动扩大
    Console.WriteLine("	 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("	 Length:"+ sb.Length);
    sb.Append('b',4);
    Console.Write("Capacity:"+ sb.Capacity);//这里的Capacity会自动扩大
    Console.WriteLine("	 Length:"+ sb.Length);
    sb.Append('c',6);
    Console.Write("Capacity:"+ sb.Capacity);//这里的Capacity会自动扩大
    Console.WriteLine("	 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)+"	 Capacity:"+ sb.Capacity+"	 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)+"	 Capacity:"+ sb1.Capacity+"	
    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的控制



  • 相关阅读:
    10个超实用的PHP代码片段
    MySQL支撑百万级流量高并发的网站部署详解
    程序员总结:帮助你早些明白一些道理
    50个最常用的UNIX / Linux命令(结合实例)
    php.ini 核心配置选项说明
    智能指针的死穴 循环引用
    滥用vector带来的瓶颈
    JS——层的遮罩效果
    【趣】无广告看视频
    【SQLServer】远程访问数据库进行配置
  • 原文地址:https://www.cnblogs.com/moonache/p/5168741.html
Copyright © 2020-2023  润新知