[英]which datastructure for this hashmap scenario
我有一個場景,我將值存儲在hashmap中。
鍵是字符串
fruits
fruits_citrus_orange
fruits_citrus_lemon
fruits_fleshly_apple
fruits_fleshly
fruits_dry
等等。
值是一些對象。 現在對於給定的輸入說fruits_fleshly我需要檢索它以“fruits_fleshly”開頭的所有情況在上面的例子中我需要獲取
fruits_fleshly_apple
fruits_fleshly
一種方法是在所有鍵上執行String.indexOf。 有沒有其他有效的方法來做到這一點,而不是迭代地圖中的所有鍵
迭代地圖似乎是非常簡單和直截了當的方式。 但是,由於您不想自己迭代鍵,因此如果您可以使用第三方庫,則可以使用Guava的 Maps#filterEntries
。
以下是它的工作原理:
Map<String, Object> = Maps.filterEntries(
yourMap,
Predicate.containsPattern("^fruits_fleshly"));
但是,那也會在后院的地圖上迭代。 因此,如果您對效率感到困擾,迭代仍然存在。
雖然這些是字符串,但對我來說,看起來這些是某些類別和子類別,如水果,新鮮水果,水果柑橘等。
如果是這種情況,您可以改為實現樹數據結構。 這對搜索操作最有效。
由於Tree
具有父子結構,因此存在根節點和子節點。 你可以有這樣的結構:
(0) (1) (2)
fruit
|_____citrus
| |_____lemon
| |_____orange
|
|_____freshly
|_____apple
|_____
在這種結構中,如果你想搜索柑橘類水果,你可以去柑橘,並列出它的所有孩子。 最后,您可以通過將名稱連接為從根到葉的路徑來構造全名。
由於HashMap沒有維護其鍵的任何順序,因此對於此問題不是一個非常好的選擇。 更好的選擇是TreeMap:它具有檢索一系列鍵的子映射的方法。 這些方法在O(log n)時間(n個條目)中運行,因此它比迭代密鑰更好。
Map subMap = myMap.subMap("fruits_fleshly", true, "fruits_fleshly\uffff", true);
hashmap的本質意味着沒有辦法對鍵進行“喜歡”的比較 - 你必須遍歷它們才能找到key.startsWith(input)
。
我想你可以嵌套哈希映射並拆分你的密鑰。 例如,
{
"fruits":{
"citrus":{
"orange":(value),
"lemon":(value)
},
"fleshly":{
"apple":(value),
"":(value)
}
}
}
...等等。
性能影響可能在小范圍內可怕,但在家庭作業環境中可能無關緊要,但如果您處理大量數據並且只有幾層嵌套,則可能並不那么糟糕。
或者,使用List of Categories(子類別)和條目列表創建Category對象。
我相信Radix Trie正是您所尋找的。 它與@ ay89解決方案類似。
您可以使用此開源庫Radix Trie示例 。 它的性能優於O(log(N))。 您將能夠找到一個平均恆定時間(搜索關鍵字字符串中的下划線數)分配給鍵的哈希映射,並使用Radix Trie.fruits的一個不錯的實現.fruit_citrus_orange fruits_citrus_lemon fruits_fleshly_apple fruits_fleshly fruits_dry
Trie<String, Map> trie = new PatriciaTrie<>;
trie.put("fruits", hashmap1);
trie.put("fruits_citrus_orange", hashmap2);
trie.put("fruits_citrus_lemon", hashmap3);
trie.put("fruits_fleshly_apple", hashmap4);
trie.put("fruits_fleshly", hashmap5);
Map.Entry<String, Map> entry = trie.select("fruits_fleshy");
如果你只想通過select返回一個hashmap,那么如果你實現自己的Radix Trie,你可能會獲得更好的性能。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.