点击这里给我发消息

可怕的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 马朋飞

posted @ 2013-02-27 10:02  鹏@  阅读(310)  评论(0编辑  收藏  举报
点击这里给我发消息