Я хочу получить случайные ключи и их соответствующие значения с карты. Идея состоит в том, что случайный генератор выбирает ключ и отображает это значение. Сложная часть состоит в том, что и ключ, и значение будут строками, например myMap.put("Geddy", "Lee")
.
Выбор случайных ключей и наборов значений из карты в Java
Ответ 1
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);
Ответ 2
Этот вопрос должен помочь вам Есть ли способ получить значение HashMap случайным образом в Java?, а это также Выбор случайного элемента из набора, потому что HashMap
поддерживается HashSet
. Это будет либо O(n)
время и постоянное пространство, либо это будет O(n)
дополнительное пространство и постоянное время.
Ответ 3
Если вы не возражаете против потраченного впустую пространства, один подход заключается в том, чтобы отдельно хранить 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);
Этот подход также означает, что добавление пары ключ-значение намного дешевле, чем удаление. Чтобы добавить пару "ключ-значение", вы проверили бы, будет ли ключ уже на карте (если ваши значения могут быть нулевыми, вам придется отдельно вызывать map.containsKey
; если нет, вы можете просто добавить ключ- и посмотрите, возвращается ли "старое значение" null)
. Если ключ уже находится на карте, список не изменяется, но если нет, вы добавляете ключ в список (операция O (1) для большинство списков). Однако удаление пары ключ-значение включает операцию O (N) для удаления ключа из списка.
Если пространство является большой проблемой, но производительность меньше, вы также можете получить Iterator
над набором записей карты (Map.entrySet()
) и пропустить randIndex
записи перед возвратом того, который вы хотите. Но это будет операция O (N), которая как бы поражает всю точку карты.
Наконец, вы можете просто получить набор записей toArray()
и случайным образом индексировать его. Это проще, хотя и менее эффективно.
Ответ 4
Я бы скопировал карту в массив и выделил запись, которую вы хотите наугад. Это позволяет избежать необходимости также искать значение из ключа.
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);
}
Ответ 5
Используйте выборку коллектора, чтобы выбрать список случайных ключей, затем вставьте их в карту (вместе с их соответствующими значениями в исходной карте. )
Таким образом, вам не нужно копировать весь 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);
}
Ответ 6
Если ваши ключи целые или что-то сопоставимые, вы можете использовать TreeMap для этого.
TreeMap<Integer, Integer> treeMap = new TreeMap<>();
int key = RandomUtils.ranInt(treeMap.lastKey());
int value = treeMap.ceilingKey(key);
Ответ 7
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()));
}
Ответ 8
Прошло некоторое время с момента загрузки с помощью java, но не keySet() дает вам список, который вы можете выбрать из числа с числовым индексом? Я думаю, вы можете выбрать случайное число и выбрать его из набора ключей MyMap, а затем выбрать соответствующее значение из myMap. Не могу проверить это прямо сейчас, но, похоже, это ударит меня как можно больше!