這真的是您應該煩惱的嗎? java.util.ArrayList和java.util.HashMap從根本上有問題嗎? 對于大多數源代碼,答案是–不; 這些實現完全可以。 但是,一如既往,細節決定成敗。 并存在情況下,當是內置到功能設置集合API不夠充分,或者您找到標準的集合設置成開銷太高了您的喜好。 在過去的幾年中,我們不斷地發現了同樣的問題。 并且認為分享經驗會很好–希望它可以節省一兩天的時間。 通過避免另一種雙向Map實現或理解為什么他的HashSet消耗的內存比預期多10倍來實現。
我們已將評論分為兩個不同的集合庫組。 首先,它們為標準Collections API提供了其他功能。 在這個小組中,我們有Guava和Apache Commons Collections這樣的玩家。 另一組Collection庫可以在某些方面發揮作用。 在這個小組中,我們看到諸如Trove,fastutil和Huge Collections之類的庫。 我們從添加功能的庫開始概述,然后進入面向性能的環境。
集合API
每個Java開發人員都應該熟悉的真正基本的API之一。 但是,至少每個月一次,我們會碰到一個真正有創造力或者只是不習慣于熟悉Collections API的人編寫的代碼。
因此,如果當ArrayList更合適或者不了解TreeSet和TreeMap之間的區別時,您的任何一個同事也正在使用Vector,那么Janeve George就整個API進行了很好的概述 ,并解釋了何時使用哪種類型的Collections。 。
引用我們今天所知道的Collections API的起源也很好。 Collections API中可用的大多數抽象,結構和功能最初都是由Doug Lea在其collections包中設計的。
番石榴
Guava是Google的前身,它是在多個Google產品中使用的一組庫。 該庫的重要部分專用于館藏。 例如,您需要時就應該查看番石榴:
- 100%線程安全的集合–簽出ImmutableCollections
- 輕松計算集合中特定元素的出現次數– MultiSet和SortedMultiSet可以節省您的一天。
- 想要實現未標記的有向圖? Multimap是您最好的朋友。
- 是否需要實現一個鍵和值都唯一且都應可用作搜索值的鍵的映射? 番石榴的雙向地圖將幫助您。
…還有更多有趣且有用的實現,您可以從項目的主頁中檢出。
Apache Commons集合
Commons Collections由多個Apache項目使用,如果您需要其他功能,例如Commons Collections,它是一個不錯的附加組件:
- FIFO / LIFO實現–查看“ 隊列和緩沖區” 。
- 一個集合可以保留同一元素的多個副本? 放進袋里 實施。
- 一個Map,其中元素按特定順序排列,但未根據鍵的compareTo()進行排序-解決方案以OrderedMap的形式提供。
為了使本文的字符數保持在30,000個以內,我將不介紹所有優點,但是我可以驗證Apache Commons Collections項目中還有很多不錯的實用程序和工具。
寶庫
如果您保存在集合中的只是數字,那么Trove可能會幫助您提高性能并減少內存開銷。 Trove是一組收集類,專門用于保存原語。 如果您還記得的話,它們消耗的內存比對象包裝對象少。
快速測試表明,在較大的collection上,Trove實現所需的堆至少比標準Java Collection實現少三倍。 如果您認為這是無關緊要的開銷,則在32位計算機上,包含100,000個整數的Map使用java.util.HashMap需要6.3MB的堆,而使用Trove則需要1.8MB的堆。 現在,從包含數以千萬計的元素的集合來看,已經開始有意義。
與Trove相當的東西,即Apache Commons Primitives和Java的Primitive Collections似乎都被放棄了。 這兩種情況的最新版本都始于2003年。
大量收藏
如果您要消除的痛點與舊一代中收集到的大型集合導致的長時間GC暫停有關,則應查看Huge Collections 。 它們完全將內容保留在堆外,因此幾乎完全不影響垃圾收集。 從下面的數據集可視化中可以看出,作者正在發布用在GC上的數字,這些數字在數據結構上具有不同的大小:
高度可擴展的Java
需要鎖定不重要的解決方案嗎? 是否需要在具有數十個或數百個內核的環境中使用數據結構? 然后為您創建了高度可擴展的Java 。 感謝Cliff Click對此。
fastutil
需要工作與超過2 ^ 31個元素真正的大集合? 查看fastutil –它為您提供了與這些野獸一起工作的數據結構。 從歷史上看,這個問題并不是什么大問題。 為什么-因為我們沒有這么大的數據結構。 而且在極少數情況下,我們確實有這種大小的結構,在API本身施加2 ^ 31的限制之前,我們會遇到RAM限制。 因此,在那種情況下,我們改為創建一個包含100億個百萬元素的單一集合。
其他
無論如何,本節最后的圖書館比(引起關注的)圖書館要糟糕得多。 只是這些是我們還沒有機會在實踐中嘗試的Collections。 至少直到本文發表為止。 但是,由于我們的讀者,我們得到了一些提示,并在1月9 日發布了已發表的文章部分:
Javolution –使用Javolution集合的主要原因是它們具有時間確定性(最大執行時間非常接近最小執行時間),并且它們是RTSJ-Safe。 因此,如果您要編寫硬性或軟性實時應用程序,并且必須處理執行期限和CPU時間預算,請進行檢查 。
高盛收藏 。 您可能喜歡或可能不喜歡投資銀行業務,但是GS Collections背后的概念肯定很有趣。 該庫為常用操作添加了許多便利方法,否則需要您編寫Iterators和匿名類。 還有一種說法是,GS集合還消耗更少的CPU周期和堆。 自2005年以來的圖書館顯然已經使用了高盛的內部應用程序和我們渴望通過嘗試一下自己 。 圖書館還隨附了GS Collections Kata項目中包裝好的實用培訓材料。
摘要
正如我們文章中經常發生的那樣-在您手頭的95%的問題中,此處介紹的庫除了使您的設置復雜之外,不會添加任何其他內容。 但是在極少數情況下,當您需要其他功能或需要擠出最后的性能時–熟悉環境非常好。 在自己編寫半熟的解決方案之前,請做出明智的選擇。
完全免責聲明:在熟悉所有上述解決方案之后,由于與性能相關的各種原因,我們仍然最終構建了自己的解決方案。 但是,通常情況下,作為–javaagent來跟蹤所有對象的創建和銷毀,您并不一定會受到性能的限制,并且可能會產生更多開銷。 在這種情況下,您可以嘗試現有的解決方案,而不是從頭開始構建自己的解決方案,從而可能會更好。
參考:從我們的JCG合作伙伴 Vlumimir Sor(位于Plumbr博客)中 選擇您的收藏庫 。
翻譯自: https://www.javacodegeeks.com/2013/01/selecting-your-collections-library.html