C# String.Replace()与StringBuilder.Replace()的比较

C# String.Replace()与StringBuilder.Replace()的比较,c#,.net,.net-4.0,replace,C#,.net,.net 4.0,Replace,我有一个字符串,其中我需要用字典中的值替换标记。它必须尽可能高效。使用string.replace执行循环只会消耗内存(记住,字符串是不可变的)。StringBuilder.Replace()是否会更好,因为它是为处理字符串而设计的 我希望避免使用正则表达式,但如果这是一种更有效的方法,那就这样吧 注意:我不关心代码的复杂性,只关心它的运行速度和占用的内存 平均统计数据:长度255-1024个字符,字典中有15-30个键。这可能有帮助: 简短的回答似乎是String.Replace速度更快,尽

我有一个字符串,其中我需要用字典中的值替换标记。它必须尽可能高效。使用string.replace执行循环只会消耗内存(记住,字符串是不可变的)。StringBuilder.Replace()是否会更好,因为它是为处理字符串而设计的

我希望避免使用正则表达式,但如果这是一种更有效的方法,那就这样吧

注意:我不关心代码的复杂性,只关心它的运行速度和占用的内存

平均统计数据:长度255-1024个字符,字典中有15-30个键。

这可能有帮助:

简短的回答似乎是String.Replace速度更快,尽管它可能会对内存占用/垃圾收集开销产生更大的影响

stringbuilder.replace[比String.replace]更好吗

是的,好多了。如果可以估计新字符串的上限(看起来可以),那么它可能足够快了

当您像这样创建它时:

  var sb = new StringBuilder(inputString, pessimisticEstimate);

然后StringBuilder将不必重新分配其缓冲区

是的,
StringBuilder
将提高速度和内存(基本上是因为它不会在每次使用它进行操作时创建字符串实例-
StringBuilder
始终使用相同的对象操作)。下面是一个包含一些详细信息的示例。

将数据从字符串转换为StringBuilder并返回需要一些时间。如果只执行一次更换操作,则StringBuilder固有的效率改进可能无法弥补这一时间。另一方面,如果将字符串转换为StringBuilder,然后对其执行许多替换操作,并在最后将其转换回,则StringBuilder方法往往更快。

而不是对整个字符串运行15-30次替换操作,使用数据结构之类的东西来保存字典可能更有效。然后,您可以循环输入字符串一次,以执行所有搜索/替换操作。

使用RedGate Profiler,使用以下代码

class Program
    {
        static string data = "abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz";
        static Dictionary<string, string> values;

        static void Main(string[] args)
        {
            Console.WriteLine("Data length: " + data.Length);
            values = new Dictionary<string, string>()
            {
                { "ab", "aa" },
                { "jk", "jj" },
                { "lm", "ll" },
                { "yz", "zz" },
                { "ef", "ff" },
                { "st", "uu" },
                { "op", "pp" },
                { "x", "y" }
            };

            StringReplace(data);
            StringBuilderReplace1(data);
            StringBuilderReplace2(new StringBuilder(data, data.Length * 2));

            Console.ReadKey();
        }

        private static void StringReplace(string data)
        {
            foreach(string k in values.Keys)
            {
                data = data.Replace(k, values[k]);
            }
        }

        private static void StringBuilderReplace1(string data)
        {
            StringBuilder sb = new StringBuilder(data, data.Length * 2);
            foreach (string k in values.Keys)
            {
                sb.Replace(k, values[k]);
            }
        }

        private static void StringBuilderReplace2(StringBuilder data)
        {
            foreach (string k in values.Keys)
            {
                data.Replace(k, values[k]);
            }
        }
    }
类程序
{
静态字符串数据="ABCDEFGHIGKLMNOPQRSTUVWXYZAB EFGHIGKLMNOPQRSTUVXYZAB EFGHIGKLMNOPQRSTUVWXYZAB EFGHIGKLMNOPQRSTUVWXYZAB EFGHIGKLMNOPQRSTUVWXYZAB EFGHIGKLMNOPQRSTUVWXYZAB EFGHIGHKLMOPQRSTUVWXYZAB EFGHIGKLMNOPQRSTUVWXYZAB EFGHIGKLMNOPQRSTUVWXYZAB EFGHIGKLMNOPQRSTUVWXYZAB EFGHIGKLMNOPQRSTUVWXYZAB EFGHIGKLKLKLKLKLZUKLKKLKLKLKKLZUKLKKKKKKKKKKKLKLZUVWXYZAB EFGLmnopqrstuvxyzabefghijklmnopqrstuvxyzabefghijklmnopqrstuvxyzabefghijklmnopqrstuvxyzabefghijklmnopqrstuvxyzabefghijklmnopqrstuvxyzabefghijklmnopqrstuvxyzabefghijklmnopqrstuvxyzabefghijklmnopqrstuvxyzabefghijklmnopqlstuvzabefghijklmnopqlstuvzabefghijklmnopvzabefghijklmnopvzabefghijklmnwxyzabcd efghjklmnopqrstuvxyzabefghjklmnopqrstuvxyzabefghjklmnopqrstuvxyzabefghjklmnopqrstuvxyzabefghjklmnopqrstuvxyzabefghjklmnopqrstuvxyzabefghjklmnopqrstuvwxyzabefghjklmnopqrstuvwxyzabefghjklmnopqrstuvxyzabd efghjklmhijklmnopqrnopqrstuvxyzabefghjklmnopqrstuvxyzabefghjklmnopqrstuvxyzabefghjklmnopqrstuvxyzabefghjklmnopqrstuvxyzabefghjklmnopqrstuvxyzabefghjklmnopqrstuvxyzabefghjklmnopqrstuvxyzabefghjklmnopqrstuvxyzabefghjklmnopqrstuvxyzabefghjklmnopqrstuvxyzabefghjklmnopqrstuvzabefghjklmnopqrstuvxyzabefghjklmnopqrstubjklmnopvwjklstuvxyzabcdefghijklmnopqrstuvxyzabcdefghijklmnopqrstuvxyz”;
静态字典值;
静态void Main(字符串[]参数)
{
Console.WriteLine(“数据长度:“+Data.length”);
值=新字典()
{
{“ab”,“aa”},
{“jk”,“jj”},
{“lm”,“ll”},
{“yz”,“zz”},
{“ef”,“ff”},
{“st”,“uu”},
{“op”,“pp”},
{“x”,“y”}
};
替换(数据);
StringBuilderReplace1(数据);
StringBuilderReplace2(新的StringBuilder(data,data.Length*2));
Console.ReadKey();
}
私有静态void StringReplace(字符串数据)
{
foreach(values.Keys中的字符串k)
{
数据=数据。替换(k,值[k]);
}
}
私有静态void StringBuilderReplace1(字符串数据)
{
StringBuilder sb=新的StringBuilder(数据,数据长度*2);
foreach(values.Keys中的字符串k)
{
sb.替换(k,值[k]);
}
}
私有静态无效StringBuilderReplace2(StringBuilder数据)
{
foreach(values.Keys中的字符串k)
{
数据。替换(k,值[k]);
}
}
}
  • 字符串替换=5.843ms
  • StringBuilder.Replace#1=4.059ms
  • Stringbuilder.Replace#2=0.461ms
字符串长度=1456

stringbuilder#1在方法中创建stringbuilder,而#2不创建stringbuilder,因此性能差异很可能最终是相同的,因为您只是将该工作移出了方法。如果您从stringbuilder而不是字符串开始,那么#2可能是一种替代方法


就内存而言,使用RedGateMemory profiler,在进行stringbuilder将赢得总体胜利的许多替换操作之前,无需担心任何问题。

这将在很大程度上取决于给定字符串中平均存在多少标记

StringBuilder和String之间搜索键的性能可能类似,但如果必须在单个字符串中替换多个标记,StringBuilder将获胜

如果y
using System;
using System.Diagnostics;
using System.IO;
using System.Text;
using System.Windows;

void StringReplace_vs_StringBuilderReplace( string file, string word1, string word2 )
{
    using( FileStream fileStream = new FileStream( file, FileMode.Open, FileAccess.Read ) )
    using( StreamReader streamReader = new StreamReader( fileStream, Encoding.UTF8 ) )
    {
        string text = streamReader.ReadToEnd(),
               @string = text;
        StringBuilder @StringBuilder = new StringBuilder( text );
        int iterations = 10000;

        Stopwatch watch1 = new Stopwatch.StartNew();
        for( int i = 0; i < iterations; i++ )
            if( i % 2 == 0 ) @string = @string.Replace( word1, word2 );
            else @string = @string.Replace( word2, word1 );
        watch1.Stop();
        double stringMilliseconds = watch1.ElapsedMilliseconds;

        Stopwatch watch2 = new Stopwatch.StartNew();
        for( int i = 0; i < iterations; i++ )
            if( i % 2 == 0 ) @StringBuilder = @StringBuilder .Replace( word1, word2 );
            else @StringBuilder = @StringBuilder .Replace( word2, word1 );
        watch2.Stop();
        double StringBuilderMilliseconds = watch1.ElapsedMilliseconds;

        MessageBox.Show( string.Format( "string.Replace: {0}\nStringBuilder.Replace: {1}",
                                        stringMilliseconds, StringBuilderMilliseconds ) );
    }
}