我正在使用large ArrayList<HashMap<A,B>>,并且我将反复需要从随机HashMap中选择一个随机密钥(并对其进行处理)。选择随机的HashMap很简单,但是我应该如何从此HashMap中选择一个随机密钥呢?
ArrayList<HashMap<A,B>>
速度很重要(因为我需要这样做10000次,并且哈希图很大),因此,仅选择[0,9999]中的随机数k,然后.next()对迭代器进行k次,实际上是不可行的。 同样,在每次随机选择时都不能将HashMap转换为数组或ArrayList。 请在回复之前阅读此内容。
.next()
从技术上讲,我认为这应该可行,因为HashMap将其密钥存储在Entry[]内部,并且从数组中随机选择很容易,但是我不知道如何访问它Entry[]。因此,Entry[]欢迎访问内部的任何想法。当然也欢迎其他解决方案(只要它们不消耗哈希图大小中的线性时间)。
Entry[]
注意: 试探法很好,因此,如果有一种方法排除了1%的元素(例如,由于多个填充的桶),那根本没有问题。
我设法找到一个解决方案,而不会降低性能。我将其张贴在这里,因为它可能对其他人有帮助-并可能回答有关此主题的几个未解决的问题(我将在以后搜索)。
您需要的是第二个Set类似于自定义的数据结构来存储密钥- 而不是此处建议的列表。类似于列表的数据结构要从中删除项目成本很高。所需的操作是在固定时间内添加/删除元素(以使其与HashMap保持最新),以及选择随机元素的过程。下面的类MySet正是这样做的
Set
MySet
class MySet<A> { ArrayList<A> contents = new ArrayList(); HashMap<A,Integer> indices = new HashMap<A,Integer>(); Random R = new Random(); //selects random element in constant time A randomKey() { return contents.get(R.nextInt(contents.size())); } //adds new element in constant time void add(A a) { indices.put(a,contents.size()); contents.add(a); } //removes element in constant time void remove(A a) { int index = indices.get(a); contents.set(index,contents.get(contents.size()-1)); contents.remove(contents.size()-1); indices.set(contents.get(contents.size()-1),index); indices.remove(a); } }