分享一个String Replace方法
在上一编 文章里分享了自定义实现一个高效的String Split方法,接下来同样分享一下String相关操作的函数Replace.通过反编译查看String的Replace方法是内置实现无法查看具体 实现源码,因此无法推断出String的Replace方法实现如何;不过出于好奇自己手动去实现一个对应的Replace函数,从测试情况来看其效率相对来说比String的Replace方法要好些.
测试描述
为了让测试更全面所以进行不同内容替换和处理的不同次数添加到测试中.
-
测试用的String数据
Cache-Control:public, max-age=0
Content-Encoding:gzip
Content-Length:9480
Content-Type:text/html; charset=utf-8
Date:Wed, 31 Oct 2012 14:17:06 GMT
Expires:Wed, 31 Oct 2012 14:17:05 GMT
Last-Modified:Wed, 31 Oct 2012 14:17:05 GMT
P3P:CP=NON DSP COR ADM CUR DEV TAI OUR IND NAV PRE STA
P3P:CP=NON DSP COR ADM CUR DEV TAI OUR IND NAV PRE STA
Server:Microsoft-IIS/7.5
Set-Cookie:smark=Branch=default&IsProject=1; domain=.codeplex.com; expires=Fri, 31-Oct-2042 14:17:06 GMT; path=/
Vary:Accept-Encoding
X-AspNet-Version:4.0.30319
X-AspNetMvc-Version:4.0
X-Powered-By:ASP.NET
-
测试相关方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | static void StringReplace( string value, string olddata, string newdata) { for ( int i = 0; i < count; i++) { value.Replace(olddata, newdata); } } static void StringExtendReplace( string value, string olddata, string newdata) { for ( int i = 0; i < count; i++) { StringExtend.Replace(value,olddata, newdata); } } |
-
具体测试代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 | static void Main( string [] args) { value.Replace( "1" , "010" ); StringExtend.Replace(value, "1" , "010" ); Console.SetOut( new System.IO.StreamWriter( "test.txt" )); count = 1; TestReplace(value, "1" , "010" ); count = 10; TestReplace(value, "C" , "010" ); count = 100; TestReplace(value, "W" , "010" ); count = 1000; TestReplace(value, "A" , "010" ); count = 10000; TestReplace(value, "0" , "010" ); count = 100000; TestReplace(value, ":" , "010" ); count = 1; TestReplace(value, "ASP.NET" , "ASPX" ); count = 10; TestReplace(value, "2012" , "2048" ); count = 100; TestReplace(value, "Wed" , "MVC" ); count = 1000; TestReplace(value, "Content" , "TESTOPQ" ); count = 10000; TestReplace(value, "ASP.NET" , "ASPX" ); count = 100000; TestReplace(value, "OUR" , "BBQ" ); Console.Out.Flush(); Console.Read(); } static void TestReplace( string value, string olddata, string newdata) { Console.WriteLine( "=========[Count:{0}\t ({1} To {2})]===============" , count, olddata, newdata); System.Diagnostics.Stopwatch sw = new System.Diagnostics.Stopwatch(); sw.Reset(); sw.Start(); StringExtendReplace(value, olddata, newdata); sw.Stop(); Console.WriteLine( "StringExtendReplace:\t{0}ms" , sw.Elapsed.TotalMilliseconds); sw.Reset(); sw.Start(); StringReplace(value, olddata, newdata); sw.Stop(); Console.WriteLine( "StringReplace:\t\t{0}ms" , sw.Elapsed.TotalMilliseconds); Console.WriteLine( "" ); } |
-
测试结果
=========[Count:1(1 To 010)]===============
StringExtendReplace:0.1728ms
StringReplace:0.1654ms
=========[Count:10(C To 010)]===============
StringExtendReplace:0.0538ms
StringReplace:0.1002ms
=========[Count:100(W To 010)]===============
StringExtendReplace:0.4561ms
StringReplace:0.9015ms
=========[Count:1000(A To 010)]===============
StringExtendReplace:5.4919ms
StringReplace:11.0184ms
=========[Count:10000(0 To 010)]===============
StringExtendReplace:52.7016ms
StringReplace:96.3369ms
=========[Count:100000(: To 010)]===============
StringExtendReplace:633.8311ms
StringReplace:1025.9258ms
=========[Count:1(ASP.NET To ASPX)]===============
StringExtendReplace:0.0067ms
StringReplace:0.0084ms
=========[Count:10(2012 To 2048)]===============
StringExtendReplace:0.0424ms
StringReplace:0.0889ms
=========[Count:100(Wed To MVC)]===============
StringExtendReplace:0.4074ms
StringReplace:0.8477ms
=========[Count:1000(Content To TESTOPQ)]===============
StringExtendReplace:4.5297ms
StringReplace:7.6571ms
=========[Count:10000(ASP.NET To ASPX)]===============
StringExtendReplace:43.2199ms
StringReplace:82.9951ms
=========[Count:100000(OUR To BBQ)]===============
StringExtendReplace:442.286ms
StringReplace:841.7506ms
方法源代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 | [ThreadStatic] static char [] mTempChars; protected static char [] GetTempData() { if (mTempChars == null ) mTempChars = new char [1024 * 64]; return mTempChars; } public static string Replace( string value, string oldData, string newData) { char [] tmpchars = GetTempData(); int newpostion = 0; int oldpostion = 0; int length = value.Length; int oldlength = oldData.Length; int newlength = newData.Length; int index = 0; int copylength = 0; bool eq = false ; while (index < value.Length) { eq = true ; for ( int k = 0; k < oldlength; k++) { if (value[index + k] != oldData[k]) { eq = false ; break ; } } if (eq) { copylength = index - oldpostion; value.CopyTo(oldpostion, tmpchars, newpostion, copylength); newpostion += copylength; index += oldlength; oldpostion = index; newData.CopyTo(0, tmpchars, newpostion, newlength); newpostion += newlength; } else { index++; } } if (oldpostion < length) { copylength = index - oldpostion; value.CopyTo(oldpostion, tmpchars, newpostion, copylength); newpostion += copylength; } return new string (tmpchars, 0, newpostion); } |
总结
通 过[ThreadStatic]来对每个线程分配一组Char[],从而达到最少Char[]的开销.细心的朋友应该会发现每个线程分析的char[]大 小为64k,换句话说这个方法替换后超过64k则会异常,不过也可以分析需要设置一个最大值.如果有需要也可以给函数添加不区分大小写替换
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 地球OL攻略 —— 某应届生求职总结
· 提示词工程——AI应用必不可少的技术
· Open-Sora 2.0 重磅开源!
· 周边上新:园子的第一款马克杯温暖上架