簡體   English   中英

隊列的兩種常見實現之間有什么區別?

[英]What are the differences between the two common implementations of a queue?

在Java中,隊列的一種實現是“圓形數組”,另一種是“鏈表”。 他們有什么區別?

就它們的使用方式而言,幾乎沒有任何區別,除非您達到隊列的大小限制(我將在稍后解釋...)

至於其他注意事項:

  • 鏈表方法是有利的,因為您可以毫不費力地動態調整隊列大小-這是鏈表的基礎。 當然,可以通過重新分配數組來復制它,但這並不是最簡單的方法。

  • 另外,在鏈表中,沒有未使用的內存:在循環陣列方法中,如果隊列的大小小於陣列的最大容量,則將有“空插槽”。 但是,這並不意味着鏈表的內存使用效率更高,因為:

  • 圓形陣列方法的優點是沒有開銷。 鏈表中的每個節點都需要存儲對下一個節點的引用-如果列表變大,這將加起來。 另一方面,循環數組只是您通過索引訪問的一塊內存,因此沒有開銷。

每種方法都有優點和缺點,但是實際上,這取決於它所使用的特定情況……並且,除非您無休止地使用隊列,否則可能不會有太大的區別。

通常,循環數組實現在重用內存方面會稍好一些,但存在以下風險:如果將過多項目添加到隊列中,則可能會增大-如果實際存儲和最大存儲容量在實踐中差異太大,則可能會容納過多的內存。

鏈表更加靈活,但是通常涉及更多的垃圾回收。

在實踐中,如果您發現代碼瓶頸取決於此選擇,我想我會感到驚訝-使用您認為最直觀的方法。

與ArrayList和LinkedList大致相同。

  • 對於陣列,您需要很好地估計隊列的大小,因為您需要為其分配存儲。 但是這樣做之后,當接近容量時,它會變得更緊湊。 “自由點”仍會占用陣列中的空間,而在LinkedList中則不會。

  • 對於鏈表,更容易從中間刪除和添加元素(盡管隊列根本不需要)。

  • 該數組是隨機訪問的,這意味着您可以快速到達位置x處的元素。 同樣,此功能在隊列中沒有用。

實現為鏈表的隊列沒有固定的大小,而實現為圓形數組(也稱為環形緩沖區)的隊列通常具有固定的大小(盡管可以調整大小,就像ArrayList調整大小的方式一樣)。 )。

鏈表實現每個元素使用更多的內存,但是數組實現需要更多的連續內存。 這兩個問題實際上只是一個重大問題,因為元素數量變得非常大。

向循環數組實現中添加/刪除元素非常便宜,因為它僅涉及調整計數器和設置引用,而鏈表實現在添加時必須分配元素,而在刪除時會產生GC開銷。

編寫代碼,使其僅使用接口,而不創建隊列。 這樣就很容易切換實現。

選擇一個實現作為開始。 我通常會使用數組變體(例如ArrayList),因為它們變小並且在當今的計算機上往往更快一些,我認為這是由於緩存(我只是做了一點基准測試,通過10000個元素隊列將10000000個元素推入了〜 ArrayBlockingQueue為8.3s,LinkedBlockingQueue為10-11)。 如果我需要索引訪問,我也會使用數組變量。 僅當列表或隊列中間有很多插入/刪除操作時,我才選擇鏈接列表變體。

如果您遇到性能問題,並且性能分析表明隊列是瓶頸(這不太可能),請對兩種隊列實現進行基准測試,然后選擇更好的一種。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM