Подтвердить что ты не робот

Выбор случайных ключей и наборов значений из карты в Java

Я хочу получить случайные ключи и их соответствующие значения с карты. Идея состоит в том, что случайный генератор выбирает ключ и отображает это значение. Сложная часть состоит в том, что и ключ, и значение будут строками, например myMap.put("Geddy", "Lee").

4b9b3361

Ответ 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. Не могу проверить это прямо сейчас, но, похоже, это ударит меня как можно больше!