2014-07-24 108 views
1

我需要隨機訪問HashMap中的鍵。現在,我正在使用設置的toArray()方法設置HashMap的keySet()返回並將其轉換爲String [](我的鍵是Strings)。然後我使用隨機來挑選String數組的一個隨機元素。隨機訪問HashMap鍵

public String randomKey() { 
    String[] keys = (String[]) myHashMap.keySet().toArray(); 
    Random rand = new Random(); 
    return keyring[rand.nextInt(keyring.length)]; 
} 

這似乎應該有一個更優雅的方式來做到這一點! 我讀過以下文章,但看起來比我做這件事更令人費解。如果下面的解決方案更好,爲什麼這樣呢? Selecting random key and value sets from a Map in Java

+0

這並不壞。只需三行代碼,並以易於使用/易於理解的方式整齊排列。 – Thilo

+0

但是你應該首先檢查空的地圖。 – Thilo

+0

我沒有讀過'隨機'變量應該保留在方法的外部,否則上面的代碼不會給出高水平的隨機性? quote:如果Random的兩個實例使用相同的種子創建,並且爲每個實例調用相同的方法調用序列,則它們將生成並返回相同的數字序列。 –

回答

1

,如果你想只使用這個類有一個HashMap沒有設施不知道鍵,以便返回一個條目,你有什麼可能是一樣好一個解決方案爲已任。

但請記住,您並不是真的受限制轉至使用HashMap

如果你將要遠遠更經常閱讀本集合不是寫,你可以創建你自己的其中既包含的映射關係的HashMap和不同的收集鍵,允許隨機訪問(如Vector)。

這樣一來,你就不會招致每次讀,必要時(添加或從您的收藏刪除項目),它只會發生一次地圖轉換爲一組,然後一個陣列的成本。

不幸的是,Vector允許多個相同的值鍵,以便你將不得不插入時抵禦那(以確保公平選擇一個隨機密鑰時)。這會增加插入成本。

刪除也將增加成本,因爲你必須尋找項目,從載體中刪除。

我不知道有一個簡單的單個集合用於這一目的。如果你想去整豬,你可以有你的當前HashMap,按鍵的Vector,然而另一HashMap鍵映射到矢量索引。

這樣一來,所有的操作(插入,刪除,變更,獲得隨機)將是O(1)時間,在時間上非常有效,也許沒有那麼在空間方面:-)

或者有一箇中途解決方案仍然使用包裝器,但是隻要您插入,更改或刪除密鑰,就會創建一個長期存在的字符串數組。這樣,您只需在需要時創建陣列,並且仍然可以攤銷成本。然後,您的類使用散列表對鍵進行高效訪問,並使用陣列進行隨機選擇。

而且變化也最小。你已經有了創建數組的代碼,你只需要創建你的包裝類,它提供了你需要的任何東西(從HashMap提供)該陣列)。


現在,我只考慮使用這些方法,如果性能實際上是一個問題,但是。您可以花費數不清的時間,以無所謂的方式更快地編碼:-)

如果您擁有的速度夠快,那就很好。

0

爲什麼不使用Collections.shuffle方法,保存到一個變量,並根據需要簡單地從頂部彈出一個。

http://docs.oracle.com/javase/7/docs/api/java/util/Collections.html#shuffle(java.util.List)

+0

簡潔,但對大型地圖來說似乎不必要的慢。沒有必要洗牌他們所有的只是選擇一個。 – Thilo

+0

我沒有看到OP在哪裏說他會選擇一個。我建議保存重新使用前的洗牌清單。 –

+0

好的,如果地圖沒有改變,並且你想重複獲得一個隨機密鑰,那就很好。使用你的方法,你甚至可以得到「無需替換」選項。 – Thilo

0

您可以避免將整個密鑰集複製到臨時數據結構中,方法是首先獲取大小,選擇隨機索引,然後遍歷鍵集合適的次數。

此代碼需要同步以避免同時修改。