高质量01. string与stringBuilder
由于使用 System.String 类会在某些场合带来明显的性能损耗,所以微软另外提供了一个类型StringBuilder来弥补String的不足。
StringBuilder并不会重新创建一个string 对象,它的效率源于预先以非托管的方式分配内存。如果StringBuilder 没有先定义长度,则默认分配的长度为16。当 StringBuilder 字符长度小于等于 16时,StringBuilder 不会重新分配内存;当 StringBuilder 字符长度大于16 小于 32时,StringBuilder 又会重新分配内存,使之成为 16的倍数。在上面的代码中,如果预先判断字符串的长度将大于16,则可以为其设定一个更加合适的长度(如32)。StringBuilder重新分配内存时是按照上次的容量加倍进行分配的。当然,我们需要注意,StringBuilder指定的长度要合适,太小了,需要频繁分配内存;太大了,浪费空间。
曾经有人问我,下面的两种字符串拼接方式,哪种效率更高:
1. private static void NewMethod8() { string a = "t"; a += "e"; a += "s"; a += "t"; } 2. private static void NewMethod7() { string a = "t"; string b = "e"; string c = "s"; string d = "t"; string result = a + b + c + d; }
答案是:两者效率都不高。不要以为前者比后者创建的字符串对象更少,事实上,两者创建的字符串对象相等,且前者进行了3次string.Contact方法调用,比后者还多了两次。
要完成这样的运行时字符串拼接(注意:是运行时),更佳的做法是使用StringBuilder类型,代码如下所示:
private static void NewMethod10() { //为了演示的需要,定义了4个变量 string a = "t"; string b = "e"; string c = "s"; string d = "t"; StringBuilder sb = new StringBuilder(a); sb.Append(b); sb.Append(c); sb.Append(d); //再次提示,是运行时,所以没有使用下面的代码 //StringBuilder sb = new StringBuilder("t"); //sb.Append("e"); //sb.Append("s"); //sb.Append("t"); string result = sb.ToString(); }
微软还提供了另外一个方法来简化这种操作,即使用string.Format方法。string.Format方法在内部使用StringBuilder进行字符串的格式化,如下面的代码所示:
-
private static void NewMethod11() { //为了演示的需要,定义了4个变量 string a = "t"; string b = "e"; string c = "s"; string d = "t"; string.Format("{0}{1}{2}{3}", a, b, c, d); }