zoukankan      html  css  js  c++  java
  • 简单看看这两个类 String和StringBuilder

      我记得以前在园子里面讨论这两个类的文章有很多很多,并且还拿出了很多的测试报告,在什么情况下,谁比谁快,在什么情况下,该用谁

    不该用谁等等这些,我这里就不比较了,我就简单看看他们里面的内部实现,那就先看看String吧。

    一:String类

      说到String类,资料上都说是存在于堆上的一个不可CURD的一个不可变的字符集,当然看到这句话之后就想要看看是不是这样的,然后就

    好奇的写了以下代码。

    1     class Program
    2     {
    3         static void Main(string[] args)
    4         {
    5             string s = "123";
    6         }
    7     }

    从上面的IL中也就仅仅发现一个ldstr指令,看得出clr把string做成了基元类型,也就没看到它具体转换成了什么样的方法,是不是调用了string

    的构造函数,这个也不清楚,也就不知道具体怎么把这个有序字符集放到堆中,不过办法还是有的,我们随便挑一个方法看看,比如简单一点的

    substring,我们看看它的源代码。

    然后我们找到了一个核心的方法,这个internalSubstring里面定义了两个指针ptr和ptr2,ptr则指向新申请的内存块的首地址,ptr2则指向原始

    字符串的首地址,最后将ptr2的位置偏移startindex个位置,最后我们就找到了终极方法string.wstrcpy。

    在string.wstrcpy方法里面,虽然看的迷迷糊糊,不过还是能看到类似这样的偏移操作,一点一点的将smem地址上的字符赋值给dmem中,

    确实也就说明了在堆上是有序的字符集。

    同样在上面的源代码中来说,substring操作并没有对原始字符串进行修改,而是把截取的值放到新申请的内存地址空间中,这也就说明了字符

    串是不可修改的说法,当然如果设计者真的要做到原位修改,那肯定也是能做到的,为了佐证下,我再举一个经常用到的concat方法,不过在

    FastAllocateString方法中,并没有看到他的源代码,所以只能说根据length申请合适的空间。

    所以结论出来了: 当你对字符串进行大量操作的时候,会产生很多的新的字符串,这些字符串会大量零碎的占据着堆空间,大多都是生存期较短

            的,所以一般都是在堆的第一代上,所以会对gc产生了比较大回收压力。

    二:StringBuilder

       看这个类的话,还是看一下它的源代码,就抽一个Append吧,从下面这个截图中看出来几个有意思的地方。

    <1> 原来StringBuilder里面维护的是一个m_ChunkChars的字符数组。

    <2> 如果当前的字符串的length<2,会直接给chunkchars数组复制,length>2的时候看到的是刚才string类中经典的wstrcpy用法,

          这个时候ptr指向的是chunkChars[chunkLength]的首地址,而不像string中申请新的内存空间,所以从这里看,比string大大的节省

        了内存空间。

    好了,具体他们的性能比较我也不说了,大家看着他们的原理凑合着用吧,简单的看看也只能看到这了,再看就漏点了。

  • 相关阅读:
    java语言yaml序列化到文件存在类型tag
    springboot项目banner生成
    mysql自动生成大量数据
    Mysql架构
    python爬虫-UnicodeDecodeError: 'utf-8' codec can't decode byte 0x8b in position 1: invalid start byte
    六 领域驱动设计-领域对象的生命周期
    五 领域驱动设计-软件中所表示的模型
    四 领域驱动设计-分离领域
    模型驱动设计的构造块
    三 领域驱动设计-运用领域模型-绑定模型和实现
  • 原文地址:https://www.cnblogs.com/huangxincheng/p/4042105.html
Copyright © 2011-2022 走看看