随着时间的推移,添加到List 会变得非常慢

我正在解析一个大约有1000行的html表。 我在每行的一个

中添加~10个字符串到list对象。 前200个左右的循环非常快,但随着时间的推移变得越来越慢。

这是我正在使用的代码:

 List myList = new List(); int maxRows = numRows; for (int i = 1; i < maxRows; i++) { TableRow newTable = myTable.TableRows[i]; string coll = string.Format("{0},{1},{2},{3},{4}",newTable.TableCells[0].Text,newTable.TableCells[1].Text,newTable.TableCells[2].Text,newTable.TableCells[3].Text,newTable.TableCells[4].Text); myList.Add(coll); label1.Text = i.ToString(); } 

我应该使用数组吗?

编辑:我将上面的代码放在一个新的方法上,该方法在一个新的Thread上运行,然后使用以下代码更新我的标签控件:

 label1.Invoke((MethodInvoker)delegate { label1.Text = i.ToString(); }); 

程序以一致的速度运行,不会阻止UI。

如果您大致知道集合中的范围(项目数),最好使用数组。

原因:如果列表已满,每次向List添加一个元素时,它会分配新的内存块以保存当前空间的两倍并复制其中的所有内容,然后继续附加其他条目,直到它变满,再添加一个分配副本周期。

以下是AFAIK的工作原理,默认情况下以16个元素开头,当你将第17个元素添加到列表中时,它会分配32个元素,然后复制16个,然后继续17到32个并重复这个过程,因此速度较慢但提供了灵活性不必事先确定长度。 这可能是你看到阻力的原因。

谢谢@Dyppl var list = new List(1000); 这也是一个优雅的选择,因为@Dyppl认为它是两个世界中最好的。

我测试了将字符串添加到列表中,并使用1000000 (100万)项的LIST_SIZE100000 (十万)项的LIST_SIZE进行基准测试。 这样我们就可以比较它的扩展方式。

我每次测试5次并平均运行时间。


 var l = new List(); for (var i = 0; i < LIST_SIZE; ++i) { l.Add("i = " + i.ToString()); } 

LIST_SIZE1000000需要1519 ms

LIST_SIZE100000需要96毫秒


 var l = new List(LIST_SIZE); for (var i = 0; i < LIST_SIZE; ++i) { l.Add("i = " + i.ToString()); } 

LIST_SIZE1000000需要1386 ms

LIST_SIZE100000需要65毫秒


 var l = new string[LIST_SIZE]; for (var i = 0; i < LIST_SIZE; ++i) { l[i] = "i = " + i.ToString(); } 

LIST_SIZE1000000需要1510 ms

LIST_SIZE100000需要66毫秒

所以,我们可以注意到两件事:

  • 列表越大,添加每个项目确实需要更多时间
  • 在1000个项目列表中,差异不应该是显而易见的

那么我会得出结论,瓶颈是你调用的其他方法之一。

使用您期望使用的容量初始化List:

 List myList = new List(maxRows); 

旁注:如果生成“非常”的大型列表,则内部增加的存储arrays会随着时间的推移总计达到您真正需要的存储量的两倍。 但是,如果1000个条目已经减速,我建议用分析器调查它的真正原因。 字符串可能变大吗?