C#中有个string类型,是个很特殊的reference type, 存储在内存中一个特殊的“静态池”中,这里是MSDN关于string的介绍:http://msdn.microsoft.com/zh-cn/library/362314fe(VS.80).aspx

由于string本身是一个不可变的字符串的集合,每次对string对象的修改都是新创建一个string对象,string有一个indexer用来访问字符串集合中的每个字符串(string str=”test test”;  Console.WriteLine(str[0]);),虽然我们可以使用indexer来访问这个内部维护的字符串集合,但是却不能直接改变他们的值; 所以对字符串逆序,大致有以下几个思路:

  1. 先把string转换为char[],然后对char[] 逆序,最后再把逆序后的char[]转化为string。
  2. 倒序遍历string,然后用字符拼接的方式组成逆序后的字符串。

先来说第一种:

第一步,把string转化为char[]:

  • [方案一]新建一个char[],用foreach循环对数组进行赋值:
  •                string str = "This is just a temporary string";
                   char[] data = new char[str.Length];
    
                   for(int i = 0; i < str.Length; i++)
                   {
                          data[i] = str[i];
                   }
                   
  • [方案二]使用string.ToCharArray()
  • string str = "This is just a temporary string";
    char[] data = str.ToCharArray();
    
    Console.WriteLine(data);
     

在我的测试中,我使用长度为16744448的字符串,运行50次,对50次的时间消耗求平均值,方案一耗时54.34311(milli seconds), 方案二耗时54.72313(milli seconds), 可以看出,这两中方法其实没有什么太大的性能上的差别,不过方案二看起来比方案一更简便一些。

第二步,对char[]进行逆序:

  • 最原始的做法
  •  for(int i = 0, j = data.Length - 1; i < j; ++i, --j)
    {
    	char temp = data[i];
    	data[i] = data[j];
    	data[j] = temp;
    }
                            
  • 或者使用位运算
  •  for(int i = 0, j = data.Length - 1; i < j; ++i, --j)
    {
    	data[i] ^= data[j];
    	data[j] ^= data[i];
    	data[i] ^= data[j];
    }
                            
  • 再或者使用系统类库
  •                         Array.Reverse(data);
    

使用位运算来做swap似乎比使用temp变量要慢一点,但是使用系统类库中的Array.Reverse(data)是最快的。

三种不同的逆序方式性能比拼:

  • 传统方法,耗时30.661764(milli seconds)
  • 位运算,耗时41.582382(milli seconds)
  • Array.Reverse, 耗时最少:24.00138(milli seconds)

最后这种方案的最终源代码如下:

			char[] data = str.ToCharArray();

			Array.Reverse(data);

			string result = data.ToString();

长度为16744448的字符串,运行50次,对50次的时间消耗求平均值, 这种算法总共消耗77.78445(milli seconds).

再来说第二种:

			StringBuilder sb = new StringBuilder(str.Length);
			for(int i = str.Length - 1; i >= 0; --i)
			{
				sb.Append(str[i]);
			}

			string result = sb.ToString();

这种方案耗时377.861412(milli seconds)

总结:

  • 字符串转数组时,直接一个个的copy和使用系统库函数性能基本一致,所以怀疑ToCharArray()这个方法内部的实现其实就是直接copy.
  • 对字符串进行逆序时,使用系统的Array.Reverse(data)能获得最高的效率, 应该去研究一下这个方法是怎么实现的了。
  • StringBuilder是专门为字符串的频繁修改而设计的,但是却并不适合拿来做逆序算法,这个可能与StringBuilder的内部实现有关,怎么说StringBuilder内部维护的应该是个List,而不是个Array。

相关文章:

  1. 使用InternalsVisibleTo给assembly添加“友元assembly”
  2. DotNet下NUnit的使用(2)—- 第一个NUnit工程
  3. Update the application configuration file automatically in C#
  4. JQuery Ajax发送GET请求乱码的解决办法
  5. How to use Sql Azure
  6. DotNet下NUnit的使用(1)—- NUnit入门
  7. 在.NET项目中使用log4net