我编写了一个小程序来测试我创建的两个独立扩展方法的速度,详细信息在以下屏幕截图中:
public static class Extensions
{
public static List<string> ParseEmails(this string[] emails, char[] charsToSplitOn)
{
List<string> list = new List<string>();
foreach (string email in emails)
{
string[] splitArr = email.Replace(" ", "").Split(charsToSplitOn, StringSplitOptions.RemoveEmptyEntries);
foreach (string item in splitArr)
{
list.Add(item);
}
}
return list;
}
public static string[] ParseEmails2(this string[] emails, char[] charsToSplitOn)
{
string str = string.Empty;
foreach (string item in emails)
{
str += item + ';';
}
return str.Replace(" ", "").Split(charsToSplitOn, StringSplitOptions.RemoveEmptyEntries);
}
}
Main方法初始化一个Stopwatch
类,以跟踪每种方法执行iterations
次的时间。
第一种方法ParseEmails
在另一个for
循环中有一个for
循环,而第二种方法'ParseEmails2'只有一个for
循环。
我希望第二种方法ParseEmails2
会更快,因为据我了解,这是在O(n)时间内完成的,而我的第一种方法ParseEmails
是在O(n ^ 2)时间内完成。
如果这是真的,那么我的结果难道不应该指出ParseEmails2
是这两种方法中的更快者吗?
答案 0 :(得分:0)
您必须准确了解O(n^2)
的含义。什么是n
?如果n对应于电子邮件的数量(在emails
数组中),则第一种方法的运行规模为O(n)
,因为您对所有电子邮件进行了一次迭代。
在第二种方法中,您使用字符串连接,这意味着在每次循环运行时都要创建一个新的字符串,导致复杂度为O(n^2)
。
更喜欢使用StringBuilder
或在循环内串联字符串的列表。
答案 1 :(得分:0)
好吧...您似乎不了解O
标记的目的,O
很少涉及性能,而更多地涉及性能的一致性。 O(n²)
的意思是抛物线,O(n)
的意思是直线,但是它没有告诉您实际时间。因此,一旦涉及到许多元素,O(n)
算法就应该更快。原因可能是您使用string
的{{1}}和+=
运算符,它们使用C#+
的{{1}}语义。
答案 2 :(得分:-1)
ParseEmails2实际上不是O(n),因为
str += item + ';';
包含一个循环。
答案 3 :(得分:-1)
您应该检查此链接。 字符串串联与构建器性能 String concatenation vs String Builder. Performance
在这种情况下,字符串生成器可能会稍微快一些,但实际上可能不足以使它烦恼。重新创建字符串的次数(因为字符串是不可变的,并且连接会强制从现有的两个字符串中创建一个新字符串)。
因为在非常一步上分配内存会导致更多时间。