在日常的开发中StringBuilder大家肯定都有用过,甚至用的很多。毕竟大家都知道一个不成文的规范,当需要高频的大量的构建字符串的时候StringBuilder的性能是要高于直接对字符串进行拼接的,因为直接使用+
或+=
都会产生一个新的String
实例,因为String对象是不可变的对象
,这也就意味着每次对字符串内容进行操作的时候都会产生一个新的字符串实例,这对大量的进行字符串拼接的场景是非常不友好的。因此StringBuilder
孕育而出。这里需要注意的是,这并不意味着可以用StringBuilder来代替所有字符串拼接的的场景,这里我们强调一下是频繁
的对同一个字符串对象进行拼接的操作。今天我们就来看一下c#中StringBuilder的巧妙实现方式,体会一下底层类库解决问题的方式。
简单示例需要注意的是,这里的不可变指的是字符串对象本身的内容是不可改变的,但是字符串变量的引用是可以改变的。
接下来咱们就来简单的示例一下操作,其实核心操作主要是Append方法
和ToString方法
,源码的的角度上来说还有StringBuilder的构造函数。首先是大家最常用的方式,直接各种Append然后最后得到结果。
StringBuilder builder = new StringBuilder();
builder.Append("我和我的祖国");
builder.Append(',');
builder.Append("一刻也不能分割");
builder.Append('。');
builder.Append("无论我走到哪里,都留下一首赞歌。");
builder.Append("我歌唱每一座高山,我歌唱每一条河。");
builder.Append("袅袅炊烟,小小村落,路上一道辙。");
builder.Append("我永远紧依着你的心窝,你用你那母亲的脉搏,和我诉说。");
string result = builder.ToString();
Console.WriteLine(result);
StringBuilder也是支持通过构造函数初始化一些数据的,有没有在构造函数传递初始化数据,也就意味着不同的初始化逻辑。比如以下操作
StringBuilder builder = new StringBuilder("我和我的祖国");
//或者是指定StringBuilder的容量,这样的话StringBuilder初始可承载字符串的长度是16
builder = new StringBuilder(16);
因为StringBuilder是基础类库,因此看着很简单,用起来也很简单,而且大家也都经常使用这些操作。
源码探究上面咱们简单的演示了StringBuilder的使用方式,一般的类似的StringBuilder或者是List这种虽然我没使用的过程中可以不关注容器本身的长度一直去添加元素,实际上这些容器的本身内部实现逻辑都包含了一些扩容相关的逻辑。上面咱们提到了一下StringBuilder的核心主要是三个操作,也就是通过这三个功能可以呈现出StringBuilder的工作方式和原理。
- 一个是
构造函数
,因为构造函数包含了初始化的一些逻辑。 - 其次是
Append
方法,这是StringBuilder进行字符串拼接的核心操作。 - 最后是将StringBuilder转换成字符串的操作
ToString
方法,这是我们得到拼接字符串的操作。
接下来咱们就从这三个相关的方法入手来看一下StringBuilder的核心实现,这里我参考的.net版本为v6.0.2
。
我们上面提到了StringBuilder的构造函数代表了初始化逻辑,大概来看就是默认的构造函数,即默认初始化逻辑和自定义一部分构造函数的逻辑,主要是的逻辑是决定了StringBuilder容器可容纳字符串的长度。
无参构造首先来看一下默认的无参构造函数的实现[点击查看源码