2012-04-30 38 views
40

我目前使用List<T>作爲隊列(使用lst[0],然後lst.removeAt(0))來保存對象。在給定的時間內最多約20個項目。我意識到有一個實際的Queue<T>類。我想知道是否有任何好處(性能,內存等)使用Queue<T>而不是List<T>充當隊列?隊列<T> vs列表<T>

+0

'也許'不是如果你不使用超過20個項目。但是你可以使用StopWatch類來測量它。 – alexn

+0

這取決於您的使用情況,如果它確實很重要。 lst.RemoveAt(0)將導致列表重定位所有元素,而隊列更智能。理論上Queue更好,但要確保你應該測量你的用例。 –

+0

您不能按索引訪問隊列。 你必須使用你出列的條目,而你不能將它們放回去。 Peek不是一個解決方案,但Count> 0可能是。 – Jay

回答

59

性能可以分析。雖然在這種情況下,你可能需要運行代碼數百萬次才能真正獲得有價值的差異。

我會這樣說:Queue<T>會暴露你的意圖更明確的人都知道隊列是如何工作的。

像隊列一樣使用的列表不是很清楚,特別是如果你有很多不必要的索引和RemoveAt(magicNumber)代碼。從代碼維護的角度來看,Dequeue是更多的消費品。

如果這會給您帶來可衡量的性能問題,您可以解決它。不要每個潛在的性能問題提前。

+7

爲什麼我們不應該預先解決所有潛在的性能問題? –

+19

@JohnIsaiahCarmona:因爲在10個元素上使用O(n^2)算法而不是O(n)算法不是性能問題。 – Jon

+12

@JohnIsaiahCarmona因爲當你不需要它時,你陷入了微觀優化的陷阱。我對這一切的看法是我們應該留意明顯的夾擊者,但是A和B之間的幾個毫秒不值得擔心,直到他們成爲問題。在大多數情況下,可維護的可讀代碼比性能更重要。 –

9

除了Queue<T>類實現隊列和List<T>類實現列表這一事實之外,還存在性能差異。

每當您從List<T>中刪除第一個元素時,都會複製隊列中的所有元素。隊列中只有20個元素可能不明顯。但是,當您從Queue<T>中取出下一個元素時,不會發生這樣的複製,並且總是會更快。如果隊列很長,則差異可能很大。

0

我想強調HugoRune已經指出的內容。隊列比列表快得多,在這個用例中,列表的內存訪問是1對n。我有一個類似的用例,但我有數百個值,我將使用Queue,因爲它的速度快了一個數量級。

有關隊列正在List上實現的說明:關鍵是「已實施」。它不會在出隊時將每個值複製到新的內存位置,而不是使用循環緩衝區。這可以在「列表頂部」完成,而不會受到直接使用List意味着的副本的處罰。

+0

除非容量是固定大小,否則不能使用循環緩衝區。 – Didaxis

30

簡短的回答:當它的使用就像一個隊列
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>List<T>距離更近,在推動和彈出操作中沒有性能差異。它們都推動結束並從數組結構中移除(兩者都是O(1))。


當然,你應該使用正確的結構,揭示了意向。在大多數情況下,它們的表現會更好,因爲它們是爲此目的而量身定製的。我相信根本沒有任何性能差異,微軟不會僅僅在框架中包含Queue<T>Stack<T>僅僅是不同的語義。如果是這樣的話,它本來就容易擴展。考慮SortedDictionary<K, V>SortedList<K, V>,兩者都完全相同,但僅通過性能特徵進行區分;他們在BCL中找到了一席之地。

+0

在加重情況下怎麼樣? –

+1

@AlexanderRyanBaggett它應該沒有什麼區別(我最好的猜測),但你應該真的使用更好地揭示意圖的結構。他們都向開發者講述了不同的故事。 – nawfal