java replace 忽略大小写_忽略字符串大小写替换的更高效实现

昨天灵感兄的一篇文章,其中仔细的比较了在.NET中做忽略字符串大小写替换的问题。并且给出了5个现有的解决方案,和详细的效率测试数据。不过仔细看完后,我对于Microsoft

VisualBasic RunTime中的String.Replace的效率不敢苟同,特别是看过C#改写的代码后,更是疑窦丛生

8b1c8b76df015d27e14584c7cbfd8cd6.gif

觉得VBString.Replace()效率有问题的主要原因是,Split()再Join()这个操作会带来大量的String碎片,这对于托管系统来说,代价是很大的。而且字符串中替换频率越高,对性能的损耗也就越是明显,后面的测试示例中我们会看到这个问题的。所以我实现的这个ReplaceEx()出发点就是避免产生String碎片,同时实现代码也不复杂,如下:

f0cd6c7f9e7ae96feae062cb48f670f0.pngprivate static string ReplaceEx(string original, string pattern, string replacement)

34031c708bfe702fe82d01ff5c6593aa.png{

587e34b10dcf5efbc0859b53470a2db3.png    int count, position0, position1;

587e34b10dcf5efbc0859b53470a2db3.png    count = position0 = position1 = 0;

587e34b10dcf5efbc0859b53470a2db3.png    string upperString = original.ToUpper();

587e34b10dcf5efbc0859b53470a2db3.png    string upperPattern = pattern.ToUpper();

587e34b10dcf5efbc0859b53470a2db3.png    int inc = (original.Length/pattern.Length)*(replacement.Length-pattern.Length);

587e34b10dcf5efbc0859b53470a2db3.png    char [] chars = new char[original.Length + Math.Max(0, inc)];

587e34b10dcf5efbc0859b53470a2db3.png    while( (position1 = upperString.IndexOf(upperPattern, position0)) != -1 )

3112b7b6526db5bc83e275260ae60525.png    {

587e34b10dcf5efbc0859b53470a2db3.png        for ( int i=position0 ; i 

587e34b10dcf5efbc0859b53470a2db3.png        for ( int i=0 ; i 

587e34b10dcf5efbc0859b53470a2db3.png        position0 = position1+pattern.Length;

eec4c0236afc26744c9c4e910bc34958.png    }

587e34b10dcf5efbc0859b53470a2db3.png    if ( position0 == 0 ) return original;

587e34b10dcf5efbc0859b53470a2db3.png    for ( int i=position0 ; i 

587e34b10dcf5efbc0859b53470a2db3.png    return new string(chars, 0, count);

4fd96b3cf02f4c7b5c8964ac8167f7af.png}

只有18行代码,要说复杂大家也不会同意吧

381a75cf2eca74f61ee030afa05233d0.gif

为了省事,直接用灵感兄的测试代码了

8b1c8b76df015d27e14584c7cbfd8cd6.gif。他的Test Case是:"要把字符串"中华aBc共和国"中的"abc"替换为"人民",注意:源子字符串是"aBc",要替换的是"abc",这里目的是要测试不区分大小写。为了测试效率,我特意先把测试字符串累加1000次,然后循环测试1000次。"。

测试数据如下:

regexp

vb

vbReplace

ReplaceEx

Replace

= 2.05845295980355s

= 0.684810220293361s

= 0.679955692692786s

= 0.535100131441287s Fastest!

= 0.0564451627231953s (直接用的String.Replace(),仅做参考用)

// .NET Framework 1.1, Windows xp sp2 en, P4 2.4G 512M.

由于substring和substringB太慢了,我都没有耐心等待其结果了,故取消了对他们的测试。前面我提到说,如果被替换字符串的替换频率增大,vb和vbReplace这两个方法的开销也会急剧增大。下面看我的测试数据,不改变测试程序的循环次数,只修改:string

segment = "中华aBc共和国";一句话。

1、string segment = "中abc华aBc共和国";

regexp

vb

vbReplace

ReplaceEx

Replace

= 3.75481827997692s

= 1.52745502570857s

= 1.46234256029747s

= 0.797071415501132s !!!= 0.178327413120941s

// ReplaceEx > vbReplace > vb > regexp

2、string segment = "中abc华aBc共abC和国";

regexp

vb

vbReplace

ReplaceEx

Replace

= 5.30117431126023s

= 2.46258449048692s

= 2.5018721653171s

= 1.00662179131705s !!!

= 0.233760994763301s

// ReplaceEx > vb > vbReplace > regexp

3、string segment = "中abc华aBc共abC和Abc国";

regexp

vb

vbReplace

ReplaceEx

Replace

= 7.00987862982586s

= 3.61050301085753s

= 3.42324876485699s

= 1.14969947297771s !!!

= 0.277254511397398s

// ReplaceEx > vbReplace > vb > regexp

4、string segment = "ABCabcAbCaBcAbcabCABCAbcaBC";

regexp

vb

vbReplace

ReplaceEx

Replace

= 13.5940090151123s

= 11.6806222578568s

= 11.1757614445411s

= 1.70264153684337s !!!(压倒优势)

= 0.42236820601501s

// ReplaceEx > vbReplace > vb > regexp

看到这里,是不是觉得ReplaceEx就是无敌的快了呢?其实我也希望是,不过在极端的情况下,就是segment中没有可以替换的pattern时,ReplaceEx就不行了:(

5、string segment = "AaBbCc";

regexp

vb

vbReplace

ReplaceEx

Replace

= 0.671307945562914s

= 0.32356849823092s

= 0.316965703741677s !!!

= 0.418256510254795s

= 0.0453026851178013s

// vbReplace > vb > ReplaceEx > regexp

在第5个测试中,ReplaceEx效率不高的原因是,其所有消耗都耗费在了这两个语句上:

f0cd6c7f9e7ae96feae062cb48f670f0.png string upperString = original.ToUpper();

f0cd6c7f9e7ae96feae062cb48f670f0.png string upperPattern = pattern.ToUpper();

如果我们使用CompareInfo和CompareOptions来进行IndexOf操作,虽然可以避免对字符串进行case转换,但是除测试5中的极端情况外,其他情况下效率都低于ReplaceEx目前的实现。

欢迎您测试运行效率,并提供更优化方案:)

BTW: 记录测试数据不用多次平均,但最好不要使用第一次编译后的运行结果。

本文转自博客园鸟食轩的博客,原文链接:http://www.cnblogs.com/birdshome/,如需转载请自行联系原博主。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值