最近用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 馬朋飛