时间:2017/5/15
作者:李国君
题目:快速查询List中指定的数据
背景:当List中保存了大量的数据时,用传统的方法去遍历指定的数据肯定会效率低下,有一个方法就是类似于数据库查询那样,根据索引直接提取数据。
项目中遇到的软件卡顿的现象,其中一部分原因是因为数据量大的原因,所以有必要提高数据查询的速度。
这里先展示一下模拟的的方法:假设List集合中有500000个点,每个点都有他的属性值xIndex(x坐标),yIndex(y坐标),text(描述),相当于10000*50的矩阵(10000列,50行),
(1,1) (xIndex,yIndex) | (2,1) | (3,1) | (。。。,。。。) |
(1,2) | (2,2) | (3,2) | (。。。,。。。) |
(1,3) | (2,3) | (3,3) | (。。。,。。。) |
(。。。,。。。) | (。。。,。。。) | (。。。,。。。) | (10000,50) |
然后,当我们知道某一xIdex后,想要提取满足当前xIdex的所有行的数据(text属性值),先看效果:
从查询耗时对比可以看出鲜明的对比。
方法介绍:
1.传统的方法就是直接遍历List集合:
//传统遍历 var objPoints = from b in listPoints where b.xIndex == Convert.ToInt32(this.tbX.Text.Trim().ToString()) select b; foreach (var item in objPoints) { showPoints(item); //显示当前点的text属性值; }
这种遍历在数据量较少时很好用,简单明了,可是当数据量较大时,它的效率就会大打折扣,原因在于我们遍历了所有的数据,对我们没有用的数据也会逐个遍历,所以效率会降低。
2.新方法是先将所有点的进行“归类”,将相同xIdex的点进行归类,归类的方法如下:
hsTemp.Clear();//清空哈希表 int TempCount = listPoints.Count; ; i < TempCount; i++) { if (hsTemp.ContainsKey(listPoints[i].xIndex.ToString()))//如果哈希表中存在key值 { hsTemp[listPoints[i].xIndex.ToString()] += "," + i.ToString();//这里和数组结构类似,改变索引值对应的value值信息 } else { hsTemp.Add(listPoints[i].xIndex.ToString(), i); } }
然后,利用哈希表查询List中的数据,代码如下:
this.richTextBox1.Text = "新方法查询结果:\n"; //objPonit = new MyPoint(); string currentPX = this.tbX.Text.Trim().ToString(); if (listPoints != null && currentPX != null) { int TempCount = listPoints.Count; && hsTemp.Count <= )//如果list中有数据而哈希表中却没有数据 { FlushTempIndex(); } if (hsTemp.ContainsKey(currentPX)) { string[] arrTempIndex = hsTemp[currentPX].ToString().Split(',');//可以直接将分好的数据放到数组中去 int TempIndexCount = arrTempIndex.Length; ; ; i < TempIndexCount; i++) { if (int.TryParse(arrTempIndex[i], out TempIndex) && TempIndex < TempCount) { showPoints(listPoints[TempIndex]); } } } }
最后给出整个项目的代码:
1.首先创建一个实体类(点)
using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace 快速查询数据.Models { public class MyPoint { public int xIndex { get; set; } public int yIndex { get; set; } public string text { get; set; } } }
2.创建好窗体应用程序,进行测试:
using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms; using 快速查询数据.Models; using System.Collections; namespace 快速查询数据 { public partial class Form1 : Form { List<MyPoint> listPoints = new List<MyPoint>(); private Hashtable hsTemp = new Hashtable(); MyPoint objPonit = null; public Form1() { InitializeComponent(); this.tbY.Enabled = false; generaPoints(); } //生成数据源 private void generaPoints() { ; ; i <= ; i++) { ; j <= ; j++) { objPonit = new MyPoint() { xIndex=i,yIndex=j,text=""+count}; count++; listPoints.Add(objPonit); } } } //执行查询 private void btQuery_Click(object sender, EventArgs e) { this.richTextBox1.Text = null; DateTime beforDT = System.DateTime.Now; //耗时巨大的代码 method2(); DateTime afterDT = System.DateTime.Now; TimeSpan ts = afterDT.Subtract(beforDT); this.textBox1.Text = ts.TotalMilliseconds.ToString()+" ms"; } //显示 private void showPoints(MyPoint objMyPoint) { this.richTextBox1.Text += "," + objMyPoint.text; } /// <summary> /// LinQ查询 /// </summary> private void method1() { this.richTextBox1.Text = "传统方法查询结果:\n"; var objPoints = from b in listPoints where b.xIndex == Convert.ToInt32(this.tbX.Text.Trim().ToString()) select b; foreach (var item in objPoints) { showPoints(item); } } /// <summary> /// List和Hashtable集合查询 /// </summary> private void method2() { this.richTextBox1.Text = "新方法查询结果:\n"; //objPonit = new MyPoint(); string currentPX = this.tbX.Text.Trim().ToString(); if (listPoints != null && currentPX != null) { int TempCount = listPoints.Count; && hsTemp.Count <= )//如果list中有数据而哈希表中却没有数据 { FlushTempIndex(); } if (hsTemp.ContainsKey(currentPX)) { string[] arrTempIndex = hsTemp[currentPX].ToString().Split(',');//可以直接将分好的数据放到数组中去 int TempIndexCount = arrTempIndex.Length; ; ; i < TempIndexCount; i++) { if (int.TryParse(arrTempIndex[i], out TempIndex) && TempIndex < TempCount) { showPoints(listPoints[TempIndex]); } } } } } public void FlushTempIndex() { hsTemp.Clear();//清空哈希表 int TempCount = listPoints.Count; ; i < TempCount; i++) { if (hsTemp.ContainsKey(listPoints[i].xIndex.ToString()))//如果哈希表中存在key值 { hsTemp[listPoints[i].xIndex.ToString()] += "," + i.ToString();//这里和数组结构类似,改变索引值对应的value值信息 } else { hsTemp.Add(listPoints[i].xIndex.ToString(), i); } } } } }