我目前正在使用List<T>
作为队列(使用lst[0]
然后lst.removeAt(0)
)来保存对象。在给定时间最多约20项。我意识到有一个实际的Queue<T>
课程。我想知道在Queue<T>
上使用List<T>
作为队列是否有任何好处(性能,内存等)?
答案 0 :(得分:69)
可以分析性能。虽然在这种情况下项目很少,但您可能需要运行代码数百万次才能真正获得有价值的差异。
我会这样说:Queue<T>
会更明确地公开您的 意图 ,人们知道队列是如何运作的。
像队列一样使用的列表不是很清楚,特别是如果你有很多不必要的索引和RemoveAt(magicNumber)
代码。从代码维护的角度来看,Dequeue
更具消费性。
如果这会给您带来可衡量的性能问题,您可以解决它。不要提前解决每个潜在的性能问题。
答案 1 :(得分:37)
简答:
当它像队列一样被使用时,Queue<T>
比List<T>
快。像列表一样使用List<T>
比Queue<T>
快。
答案很长:
对于出列操作,Queue<T>
更快,这是一个O(1)操作。数组的后续项的整个块不会向上移动。这是可能的,因为Queue<T>
不需要便于从随机位置移除,而只能从顶部移除。因此它保持一个头部(项目从Dequeue
上拉)和尾部位置(项目在Enqueue
上添加)。另一方面,从List<T>
的顶部移除需要自己将每个后续项目的位置向上移动一个。这是O(n) - 最糟糕的情况,如果你从顶部移除,这是一个出队操作。如果您在循环中出列,速度优势可能会很明显。
如果您需要索引访问,随机检索等,List<T>
会更高效。Queue<T>
必须完全枚举才能找到合适的索引位置(它不会公开IList<T>
)。
也就是说,Stack<T>
vs List<T>
更接近,推送和弹出操作没有性能差异。它们都推动结束并从阵列结构的末端移除(两者都是O(1))。
当然你应该使用揭示意图的正确结构。在大多数情况下,它们也会表现得更好,因为它们是为此目的而量身定做的。我相信,如果没有任何性能差异,微软就不会在框架中包含Queue<T>
和Stack<T>
仅用于不同的语义。如果是这样的话,那将简单易于扩展。考虑SortedDictionary<K, V>
和SortedList<K, V>
,两者都完全相同,但仅通过性能特征来区分;他们在BCL找到了一席之地。
答案 2 :(得分:11)
除了Queue<T>
类实现队列而List<T>
类实现列表这一事实外,还存在性能差异。
每次从List<T>
中删除第一个元素时,都会复制队列中的所有元素。队列中只有20个元素,可能不会引人注意。但是,当您从Queue<T>
出列下一个元素时,不会发生此类复制,并且总是会更快。如果队列很长,差异可能很大。
答案 3 :(得分:0)
我想强调HugoRune已经指出的内容。 Queue
明显快于List
,在此用例中,1
的内存访问次数为n
与List
的{{1}}。我有一个类似的用例,但我有数百个值,我将使用Queue
因为它快一个数量级。
关于在Queue
之上实施List
的说明:关键字是“已实施”。它在出列时不会将每个值复制到新的内存位置,而是使用循环缓冲区。这可以在“List
的顶部”完成,而不会直接使用List
暗示的副本。