2014-07-24 2 views
1

Мне нужно случайно получить доступ к ключам в HashMap. Прямо сейчас, я использую . Метод toArray() на . Установите, что . Функция keySet() HashMap возвращает и отличает ее как строку [] (моими клавишами являются строки). Затем я использую Случайный, чтобы выбрать случайный элемент массива String.Случайный доступ для ключей HashMap

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

Это не плохо. Всего три строки кода и аккуратно упакованы в простой в использовании/простой для понимания метод. – Thilo

+0

Но сначала нужно проверить пустую карту. – Thilo

+0

Разве я не читал, что переменная 'Random' должна храниться вне метода, иначе приведенный выше код не даст хорошего уровня случайности? quote: Если два экземпляра Random создаются с одним и тем же семенем, и для каждой из них производится одна и та же последовательность вызовов методов, они будут генерировать и возвращать идентичные последовательности чисел. –

ответ

1

Там нет возможности в HashMap вернуть запись, не зная ключ так, если вы хотите использовать только тот класс, что у вас есть, вероятно, столь же хорошее решение, так как любые.

Имейте ввиду, что вы на самом деле не являетесь . использовать HashMap.

Если вы собираетесь читать эту коллекцию далеко чаще, чем писать, вы можете создать свой собственный класс, который содержит как HashMap отображений и другой набор ключей, которая позволяет произвольный доступ (например, Vector).

Таким образом, вы не понесете затраты на преобразование карты в набор, а затем массив каждый раз, когда вы читаете , это произойдет только при необходимости (добавление или удаление элементов из вашей коллекции).

К сожалению, Vectorпозволяет множественные ключи одного и того же значения, так что вы должны защищать против того, при вставке (для обеспечения справедливости при выборе случайного ключа). Это увеличит стоимость вставки.

Удаление также будет увеличено, так как вам придется искать элемент для удаления из вектора.

Я не уверен, что для этой цели существует простая коллекция. Если вы хотите отправиться на целый свиньи, вы можете получить свой текущий HashMap, Vector ключей, и все же другойHashMap отображение ключей к векторным индексам.

Таким образом, все операции (вставка, удаление, изменение, получить-случайный) будет O (1) во времени, очень эффективным с точки зрения времени, возможно, в меньшей степени, с точки зрения пространства :-)

Или есть решение на полпути, которое все еще использует обертку, но создает многожильный массив строк всякий раз, когда вы вставляете, изменяете или удаляете ключ. Таким образом, вы только создаете массив, когда это необходимо, и вы по-прежнему амортизируете затраты. Затем ваш класс использует хэш-карту для эффективного доступа с помощью ключа и массив для случайного выбора.

И изменение там минимальное.У вас уже есть код для создания массива, вам просто нужно создать свой класс-оболочку, который обеспечивает все, что вам нужно, от HashMap (и просто передает большинство вызовов через в HashMap) плюс одна дополнительная функция для получения случайного ключа (с использованием массив).


Теперь я бы рассмотрел использование этих методов, если производительность на самом деле является проблемой. Вы можете потратить неисчислимые часы на то, чтобы сделать ваш код быстрее таким образом, чтобы это не имело значения :-)

Если у вас есть достаточно быстро, все в порядке.

0

Почему бы не использовать метод Collections.shuffle, сохраненный в переменной, и просто поместите его сверху.

http://docs.oracle.com/javase/7/docs/api/java/util/Collections.html#shuffle(java.util.List)

+0

Краткий, но для больших карт кажется излишне медленным. Не нужно перетасовывать все, чтобы просто выбрать один. – Thilo

+0

Я не вижу, где OP говорит, что он просто собирается выбрать один. Я предложил сохранить перетасованный список для повторного использования. –

+0

Хорошо, если карта не меняется, и вы хотите повторно получить случайный ключ, это будет хорошо работать. При вашем подходе вы даже можете «выбрать-без замены», если потребуется. – Thilo

0

Вы можете избежать копирования всего набора ключей во временную структуру данных, сначала получив размер, выбирая случайный индекс и затем итерируя по набору ключей соответствующее количество раз.

Этот код необходимо синхронизировать, чтобы избежать одновременных изменений.

Смежные вопросы