分享一個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

  • 測試相關方法

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);
    }
}
  • 具體測試代碼

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

 

方法源代碼

[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則會異常,不過也可以分析需要設置一個最大值.如果有需要也可以給函數添加不區分大小寫替換


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM