[英]What Algorithm is used by java.util.HashSet and java.util.TreeSet to store unique values in its structure?
我遇到過多種算法,例如Flajolet-Martin算法,HyperLogLog,以從元素列表中找出唯一的元素,並突然對Java的計算方式感到好奇。 在每種情況下,存儲和查找唯一值的時間復雜度是多少?
Flajolet -Martin和HyperLogLog算法的目的是在具有O(N)
時間和適度(比O(N)
)時間更短的N
元素流的一次通過中獲得不同元素的近似計數( 計數區別問題 )。用法。
Map
API的實現不需要解決“計數差異”問題。
(此外: TreeMap
和HashMap
已經對映射1中的條目數進行了預先計算的計數;即Map.size()
。如果您沒有遇到線程安全問題,則結果是准確的(不是近似的)。調用size()
的成本為O(1)
。維護它的成本為O(U)
,其中U
是執行的地圖添加和移除操作的數量。)
更一般而言,Flajolet-Martin算法或HyperLogLog不能/不能構成Map
數據結構的基礎。 他們沒有解決字典問題 。
HashMap
和TreeMap
使用的算法分別是哈希表和二叉樹算法。 各個javadocs中有更多詳細信息,完整的源代碼(帶有注釋)隨時可供您查看。 (例如,Google的"java.util.HashMap" source
。)
1-有趣的是, ConcurrentHashMap
無法以這種方式工作……因為更新size
字段將是並發瓶頸。 相反, size()
操作為O(N)
。
HashSet
類型使用哈希表(通常使用封閉式尋址)跟蹤其元素,而TreeSet
類型使用二進制搜索樹跟蹤其元素。 這些數據結構為“這個元素在這里嗎?”這個問題給出了確切的答案。 且在您需要100%確定地確定您之前是否看過某物的情況下非常有用,並且它們的內存使用情況通常與到目前為止所看到的元素總數成正比。
另一方面,HyperLogLog之類的基數估計器可以很好地回答“有多少個不同的元素,占或占幾個百分比?”形式的問題。 在需要粗略估計已看到多少不同事物,將所有內容放入哈希表或二進制搜索樹等方法會占用太多內存的情況下,它們非常有用(例如,如果您是一台Google Web服務器,並且您希望計算訪問您的不同IP地址),因為通常使用它們需要占用的內存量。 但是,他們不允許您回答以下形式的問題:“我以前看過這個東西嗎?” 因此不能作為任何java.util.Set
子類型的實現。
簡而言之,此處的數據結構旨在解決不同的問題。 傳統的BST和哈希表可用於精確查詢,在這些查詢中可以確定您是否已經看過某些東西是目標,並且希望能夠對所有看到的元素進行迭代。 基數估計器非常有用,您只需關心總共有多少個不同的元素,而不必關心它們是什么,也不需要確切的答案。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.