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