可怕的String (c#)
最近用c#做了个比较小工具比较手机号码,完成两个文件对比去重且合并的。由于经过查找资料发现用哈希表比较效率较高。
初步程序如下:
string[] filemobile1 = File.ReadAllText(cb_file1.SelectedItem.ToString(), Encoding.GetEncoding("gb2312")).Split(new string[] { "\r\n" }, StringSplitOptions.RemoveEmptyEntries); string[] filemobile2 = File.ReadAllText(cb_file2.SelectedItem.ToString(), Encoding.GetEncoding("gb2312")).Split(new string[] { "\r\n" }, StringSplitOptions.RemoveEmptyEntries); Dictionary<string, string> dic1 = new Dictionary<string, string>(); string result = ""; int num = 0; Stopwatch sw = Stopwatch.StartNew(); foreach (string str in filemobile1) { if (!dic1.ContainsKey(str)) { dic1.Add(str, ""); result+=str+"\r\n"; num++; } } foreach (string str in filemobile2) { if (!dic1.ContainsKey(str)) { dic1.Add(str, ""); result+=str+"\r\n"; num++; } } File.WriteAllText(Application.StartupPath + "\\11.txt", result, Encoding.GetEncoding("gb2312")); MessageBox.Show("对比完成!不重复的有" + num.ToString() + ";共用" + sw.ElapsedMilliseconds.ToString());
测试数据:文件1里有150000个号码,文件2里有50000个号码,文件1与文件2有50000左右重复号码,测试结果耗时150秒左右(太长了吧)。
后来我哥们加同事也同亲用dictionary写就用了50毫秒左右。经过对比最终发现罪魁祸首:
result+=str+"\r\n";
想必大家也明白了,因为在C#中string 是固定不变的,所以这一句会重新生成新的字符串并分配新的内存空间。
总结:所以在庞大的循环中尽量不要用涉及到string类型的修改。
现附我哥们代码:
string[] filemobile1 = File.ReadAllText(cb_file1.SelectedItem.ToString(), Encoding.GetEncoding("gb2312")).Split(new string[] { "\r\n" }, StringSplitOptions.RemoveEmptyEntries); string[] filemobile2 = File.ReadAllText(cb_file2.SelectedItem.ToString(), Encoding.GetEncoding("gb2312")).Split(new string[] { "\r\n" }, StringSplitOptions.RemoveEmptyEntries); Dictionary<string, string> dic1 = new Dictionary<string, string>(); StringBuilder result = new StringBuilder(); int num = 0; Stopwatch sw = Stopwatch.StartNew(); foreach (string str in filemobile1) { if (!dic1.ContainsKey(str)) { dic1.Add(str, ""); // result.Append(str + "\r\n"); num++; } } foreach (string str in filemobile2) { if (!dic1.ContainsKey(str)) { dic1.Add(str, ""); //result.Append(str + "\r\n"); num++; } } string[] content = new string[dic1.Keys.Count]; dic1.Keys.CopyTo(content, 0); string fileresult = string.Join("\r\n", content); File.WriteAllText(Application.StartupPath + "\\11.txt", fileresult, Encoding.GetEncoding("gb2312")); MessageBox.Show("对比完成!不重复的有" + num.ToString() + ";共用" + sw.ElapsedMilliseconds.ToString());
同样的数据测试结果只用了40毫秒。
pps:如果用StringBuilder效率是会比直接用string强太多,不过比我哥们方法慢了10毫秒,原因我认为是执行次数太多的原因。
pps:所以大的我循环中,应尽量减少操作语句,杜绝耗时操作如内存分配之类。能够在循环外一步搞定的不要在循环内一步步实现。
PPS:哥们ID 马朋飞