zoukankan      html  css  js  c++  java
  • 分享一个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则会异常,不过也可以分析需要设置一个最大值.如果有需要也可以给函数添加不区分大小写替换

    访问Beetlex的Github
  • 相关阅读:
    idea快捷键操作
    2018/2/17 SpringCloud的一个简单小介绍
    2018/2/16 解析Logback的AppenderBase源码,并举一反三的实现Logback扩展功能的思路,以及它的实际业务应用场景
    2018/2/15 ES Beats的学习笔记
    2018/2/14 x-pack的学习
    2018/2/14 自己实现ArrayList,LinkedList和Iterator,以及在此过程中对于面向对象,面向接口,还有抽象类的一些思考感悟
    2018/2/13 ElasticSearch学习笔记三 自动映射以及创建自动映射模版,ElasticSearch聚合查询
    2018/2/11 ELK技术栈之ElasticSearch学习笔记二
    2018/2/5 ELK技术栈之ElasticSearch学习笔记
    2018/1/28 RocketMq学习笔记
  • 原文地址:https://www.cnblogs.com/smark/p/2754529.html
Copyright © 2011-2022 走看看