マップからランダムなキーとそれぞれの値を取得したい。ランダムジェネレーターがキーを選択し、その値を表示するという考え方です。トリッキーな部分は、キーと値の両方が文字列になることです(たとえば、myMap.put("Geddy", "Lee")
)。
HashMap<String, String> x;
Random random = new Random();
List<String> keys = new ArrayList<String>(x.keySet());
String randomKey = keys.get( random.nextInt(keys.size()) );
String value = x.get(randomKey);
この質問はあなたの助けになるはずです JavaでHashMapの値をランダムに取得する方法はありますか? そしてこれも セットからランダムな要素を選ぶ なぜならHashMap
HashSet
によってサポートされています。それはO(n)
時間と一定の空間、またはO(n)
余分な空間と一定の時間のいずれかです。
無駄なスペースを気にしない場合、1つのアプローチは、List
にあるすべてのキーのMap
を個別に保持することです。最高のパフォーマンスを得るには、ランダムアクセスのパフォーマンスが優れているList
(ArrayList
など)が必要です。次に、0(包括的)からlist.size()
(排他的)の間の乱数を取得し、そのインデックスでキーを引き出し、そのキーを調べます。
_Random Rand = something
int randIndex = Rand.nextInt(list.size());
K key = list.get(randIndex);
V value = map.get(key);
_
また、このアプローチは、キーと値のペアを追加する方が、削除するよりも安価であることを意味します。キーと値のペアを追加するには、キーが既にマップ内にあるかどうかをテストします(値がnullになる可能性がある場合は、_map.containsKey
_を個別に呼び出す必要があります。そうでない場合は、キーと値のペアで、返される「古い値」が_null)
_かどうかを確認します。キーが既にマップにある場合、リストは変更されませんが、そうでない場合は、リストにキーを追加します(O(1)ほとんどのリストに対する操作)。ただし、キーと値のペアの削除には、リストからキーを削除するためのO(N)操作が含まれます。
スペースが大きな懸念事項であるが、パフォーマンスがそれほど高くない場合、マップのエントリセット(Map.entrySet()
)でIterator
を取得し、randIndex
エントリをスキップしてから戻ることもできます。あなたが欲しいもの。しかし、それはO(N)操作であり、マップのすべてのポイントを無効にします。
最後に、エントリセットのtoArray()
を取得し、それにランダムにインデックスを付けることができます。それは効率的ではありませんが、より簡単です。
キーが整数または同等のキーである場合、TreeMapを使用してそれを行うことができます。
TreeMap<Integer, Integer> treeMap = new TreeMap<>();
int key = RandomUtils.ranInt(treeMap.lastKey());
int value = treeMap.ceilingKey(key);
リザーバサンプリング を使用して、ランダムキーのリストを選択し、それらをマップに挿入します(ソースマップの対応する値とともに)。
この方法では、keySet
全体を配列にコピーする必要はなく、選択したキーのみをコピーする必要があります。
public static <K, V>Map<K, V> sampleFromMap(Map<? extends K, ? extends V> source, int n, Random rnd) {
List<K> chosenKeys = new ArrayList<K>();
int count = 0;
for (K k: source.keySet()) {
if (count++ < n) {
chosenKeys.add(k);
if (count == n) {
Collections.shuffle(chosenKeys, rnd);
}
} else {
int pos = rnd.nextInt(count);
if (pos < n) {
chosenKeys.set(pos, k);
}
}
}
Map<K, V> result = new HashMap<K, V>();
for (K k: chosenKeys) {
result.put(k, source.get(k));
}
return Collections.unmodifiableMap(result);
}
マップを配列にコピーし、必要なエントリをランダムに選択します。これにより、キーから値をルックアップする必要もなくなります。
Map<String, String> x = new HashMap<String, String>();
Map.Entry<String,String>[] entries = x.entrySet().toArray(new Map.Entry[0]);
Random Rand = new Random();
// call repeatedly
Map.Entry<String, String> keyValue = entries[Rand.nextInt(entries.length)];
重複を避けたい場合は、エントリの順序をランダム化できます
Map<String, String> x = new HashMap<String, String>();
List<Map.Entry<String,String>> entries = new ArrayList<Map.Entry<String, String>> (x.entrySet());
Collections.shuffle(entries);
for (Map.Entry<String, String> entry : entries) {
System.out.println(entry);
}
In some cases you might want to preserve an order you put the elements in the Set,
In such scenario you can use, This
Set<Integer> alldocsId = new HashSet<>();
for (int i=0;i<normalized.length;i++)
{
String sql = "SELECT DISTINCT movieID FROM postingtbl WHERE term=?";
PreparedStatement prepstm = conn.prepareStatement(sql);
prepstm.setString(1,normalized[i]);
ResultSet rs = prepstm.executeQuery();
while (rs.next())
{
alldocsId.add(rs.getInt("MovieID"));
}
prepstm.close();
}
List<Integer> alldocIDlst = new ArrayList<>();
Iterator it = alldocsId.iterator();
while (it.hasNext())
{
alldocIDlst.add(Integer.valueOf(it.next().toString()));
}