我需要随机访问HashMap中的键。现在,我在设置 HashMap 的keySet()上使用设置的toArray()方法返回,并将其转换为String [](我的键是字符串)。然后我使用 Random 来选择String数组的随机元素。
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 :(得分:1)
HashMap
中没有任何工具可以在不知道密钥的情况下返回条目,因此,如果您只想使用该类,那么您所拥有的内容可能与任何类型一样好。
请注意,您实际上并未限制使用HashMap
。
如果您要比编写远更多地阅读此远,您可以创建包含{{1}的自己的类的映射和允许随机访问的不同密钥集合(如HashMap
)。
这样,您每次读取时都不会产生将地图转换为集合然后将数据转换为数组的成本,只有在必要时才会发生这种情况(添加或删除您的项目)集合)。
不幸的是,Vector
允许具有相同值的多个键,因此您在插入时必须防御它(以确保在选择随机密钥时的公平性)。这会增加插入成本。
删除也会增加成本,因为您必须搜索要从向量中删除的项目。
我不确定这是一个简单的单一收藏品。如果您想要完成整个工作,您可以获得当前的Vector
,HashMap
个密钥,然后另一个 Vector
将密钥映射到矢量索引。
这样,所有操作(插入,删除,更改,获取随机)都会及时为O(1),在时间方面非常有效,在空间方面可能更少: - )
或者还有一个仍在使用包装器的中途解决方案,但每当您插入,更改或删除密钥时,都会创建一个长期存在的字符串数组。这样,您只需在需要时创建阵列,并且仍然可以分摊成本。然后,您的类使用hashmap通过键进行高效访问,使用数组进行随机选择。
那里的变化微乎其微。您已经拥有了创建数组的代码,您只需创建一个包装类,它可以提供HashMap
所需的任何内容(并且只需将大多数调用通过传递给HashMap
加上一个额外的函数来获取随机密钥(使用数组)。
现在,我只考虑使用这些方法,但性能实际上是一个问题。您可以花费无数时间以不重要的方式使代码更快: - )
如果你的东西足够快,那很好。
答案 1 :(得分:0)
为什么不使用保存到变量的Collections.shuffle
方法,只需根据需要从顶部弹出一个。
http://docs.oracle.com/javase/7/docs/api/java/util/Collections.html#shuffle(java.util.List)
答案 2 :(得分:0)
您可以避免将整个密钥集复制到临时数据结构中,首先获取大小,选择随机索引,然后在密钥集上迭代适当的次数。
需要同步此代码以避免并发修改。