情况如下:
我有一个列表,其中存储的字符串实际上是数字,可以变得相当大(数亿项)
我将数字存储为字符串,因为有一个选项可以显示一些附加信息,即文本。
因为这需要大量的内存来存储我决定我最多只能存储500万个项目。 (这只需要250-300mb)。
列表由计算输出填充。如果找到一个数字,它将被添加到列表中,此数字总是大于现有项目。
当列表达到5密耳时,我想删除第一个项目并将新项目添加到列表中。
像:
// Why is this so freaking slow???
if (_result.Count == 5000000)
_result.RemoveAt(0);
_result.Add(result);
正如你在评论中看到的那样,这非常非常非常慢。它只是将我的表现减少了15倍。花了2分钟,现在需要大约30分钟。
我尝试使用像.Skip(1).ToList
这样的linq,但是会重新创建列表,因此更慢。
列表必须保持正确的顺序,因此不能通过索引覆盖(除非你能解释一个很好的解决方法)。
我的问题:
有没有可行的方法呢?
我真的需要这里的表现,因为它可能需要检查大约10000000000个数字。这可能需要一天的时间,但一个月有点太多了:(。
需要其他信息,请随时提出,我很乐意提供。
解决方案:
这执行O(1)
// Set the _result
Queue<object> _result = new Queue<object>(5000000);
/// Inside the method
// If the count has reach it's max, dequeue the first item
if (_result.Count == 5000000)
_result.Dequeue();
_result.Enqueue(result);
答案 0 :(得分:4)
你有没有重新订购商品?如果不这样做,循环队列可以很好地工作。
System.Collections.Generic.Queue是一个,我只是仔细检查过。
为了扩展Queue的优势,这是RemoveAt
实现(大致):
for (int i = 1; i < count; i++)
items[i-1] = items[i];
count--;
由于list[0]
始终是第一项,因此您必须移动所有内容以删除第一项。
相反,队列分别跟踪第一个项目。这会将上面的代码更改为:
head++
答案 1 :(得分:1)
我建议你更好地实现循环队列。然后你将每个int推到队列的末尾,当你用完空间(由固定大小决定)时,每个操作都需要弹出第一个并按下底部。 O(1)
。
Advantage vs. Array是指在需要之前不会预先分配空间。但是,最后,考虑真的将整体存储为整体。无论您执行什么操作,都应始终将数字存储为数字。
答案 2 :(得分:0)
为什么不预先分配数组,并且有两个整数,表示数组的开始和结束。显然,他们都会开始等于0.一旦你用完房间,你就会开始环绕。
示例psuedo助手类:
class CircularArray
{
const int maxSize = 5000000;
private int[] arr = new int[maxSize];
private int start = 0;
private int end = 0;
public void Add(int value)
{
int newEnd = (end + 1) % maxSize;
if (newEnd == start)
start = (start + 1) % maxSize;
end = newEnd;
arr[end] = value;
}
public int Get(int index)
{
int newIndex = (start + index) % maxSize;
return arr[newIndex];
}
}
答案 3 :(得分:0)
当您删除ArrayList中的第一个项目时,所有其他项目都会向下移动。循环查询将允许您保留原始顺序,并消除删除列表头部时发生的耗时变化。
答案 4 :(得分:0)
可能LinkedList<T> Class
可能对您有帮助吗?在两端删除和添加是O(1)操作,但是迭代将是O(n),或者如果您在访问时需要O(1),则可以使用Dictionary
或SortedDictionary
另一个自定义实现是QueueDictionary
,当我在最后添加和删除或者开始(Queue / Dequeue)和访问值时都需要O(1)操作时,我使用它。这里的QueueDictionary:How would I implement a QueueDictionary, a combination of Queue and Dictionary in C#?