我有这个代码
private static void Count(List<DataRowSet> rows, int id, ref int count)
{
foreach (DataRowSet row in rows) {
if (row.parentId == id) {
count++;
Count(rows, row.Id, ref count);
}
}
}
和这个班
public class DataRowSet
{
public int Id;
public int parentId;
public DataRowSet(int id, int parent)
{
this.Id = id;
this.parentId = parent;
}
}
我想计算具有特定ID的
List<DataRowSet>
的每个孩子。Count(dataList, 1, ref cnt);
那行得通,但是一旦我在
dataList
中有8000多个条目,就会发生StackOverflow异常。代码也很慢,大约需要1.5秒才能找到所有条目。我该如何解决?
最佳答案
StackOverflowException
发生是因为您的递归太深了。它可以正常工作到8000,上面的所有内容对于堆栈来说实在太多了。
您可以通过使用Stack<DataRowSet>
并将项目推入其中来解决此问题,而不是递归调用该函数。
查看您的DataRowSet
类似乎是一个简单列表,因此有一种简单的方法可以通过使用ILookup<int, DataRowSet>
来提高性能。这样,您可以使用键查找任何相关项,而不必一次又一次地遍历列表。
首先,您必须将顶级项目压入堆栈。可以这样完成。
Stack<DataRowSet> stack = new Stack<DataRowSet>(
dataRows.Where(x => x.Id == id));
使用
dataRows.ToLookup
,可以按条目的ParentId
对其分组。ILookup<int, DataRowSet> dataLookup = dataRows.ToLookup(x => x.parentId);
之后,您只需要遍历
stack
直到其为空,同时推送具有正确ID的新项目。while (stack.Count > 0) {
DataRowSet currentRow = stack.Pop();
foreach (DataRowSet rowSet in dataLookup[currentRow.Id]) {
stack.Push(rowSet);
}
}
这样,您就不必再担心
StackOverflowException
了,并且性能也得到了提高。总体而言,您的新功能将看起来像这样。
private static int Count(List<DataRowSet> dataRows, int id)
{
int totalDescendants = 0;
Stack<DataRowSet> stack = new Stack<DataRowSet>(
dataRows.Where(x => x.Id == id));
ILookup<int, DataRowSet> dataLookup = dataRows.ToLookup(x => x.parentId);
while (stack.Count > 0) {
DataRowSet currentRow = stack.Pop();
foreach (DataRowSet rowSet in dataLookup[currentRow.Id]) {
totalDescendants++;
stack.Push(rowSet);
}
}
return totalDescendants;
}
可以这样称呼
int cnt = Count(dataList, 1);