Is there a way to get the value of a HashMap randomly in Java?

前端 未结 13 2013
心在旅途
心在旅途 2020-11-30 03:45

Is there a way to get the value of a HashMap randomly in Java?

相关标签:
13条回答
  • Generate a random number between 0 and the number of keys in your HashMap. Get the key at the random number. Get the value from that key.

    Pseudocode:

     int n =  random(map.keys().length());
     String key = map.keys().at(n);
     Object value = map.at(key);
    

    If it's hard to implement this in Java, then you could create and array from this code using the toArray() function in Set.

     Object[] values = map.values().toArray(new Object[map.size()]);
     Object random_value = values[random(values.length)];
    

    I'm not really sure how to do the random number.

    0 讨论(0)
  • 2020-11-30 04:06

    If you are using Java 8, findAny function in a pretty solution:

    MyEntityClass myRandomlyPickedObject = myHashMap.values().stream().findAny();
    
    0 讨论(0)
  • 2020-11-30 04:08

    It depends on what your key is - the nature of a hashmap doesn't allow for this to happen easily.

    The way I can think of off the top of my head is to select a random number between 1 and the size of the hashmap, and then start iterating over it, maintaining a count as you go - when count is equal to that random number you chose, that is your random element.

    0 讨论(0)
  • 2020-11-30 04:09

    This works:

    Random generator = new Random();
    Object[] values = myHashMap.values().toArray();
    Object randomValue = values[generator.nextInt(values.length)];
    

    If you want the random value to be a type other than an Object simply add a cast to the last line. So if myHashMap was declared as:

    Map<Integer,String> myHashMap = new HashMap<Integer,String>();
    

    The last line can be:

    String randomValue = (String) values[generator.nextInt(value.length)];
    

    The below doesn't work, Set.toArray() always returns an array of Objects, which can't be coerced into an array of Map.Entry.

    Random generator = new Random();
    Map.Entry[] entries = myHashMap.entrySet().toArray();
    randomValue = entries[generator.nextInt(entries.length)].getValue();
    
    0 讨论(0)
  • 2020-11-30 04:10

    If you are fine with O(n) time complexity you can use methods like values() or values().toArray() but if you look for a constant O(1) getRandom() operation one great alternative is to use a custom data structure. ArrayList and HashMap can be combined to attain O(1) time for insert(), remove() and getRandom(). Here is an example implementation:

    class RandomizedSet {
        List<Integer> nums = new ArrayList<>();
        Map<Integer, Integer> valToIdx = new HashMap<>();
        Random rand = new Random();
    
        public RandomizedSet() { }
    
        /**
         * Inserts a value to the set. Returns true if the set did not already contain
         * the specified element.
         */
        public boolean insert(int val) {
            if (!valToIdx.containsKey(val)) {
                valToIdx.put(val, nums.size());
                nums.add(val);
                return true;
            }
            return false;
        }
    
        /**
         * Removes a value from the set. Returns true if the set contained the specified
         * element.
         */
        public boolean remove(int val) {
            if (valToIdx.containsKey(val)) {
                int idx = valToIdx.get(val);
                int lastVal = nums.get(nums.size() - 1);
    
                nums.set(idx, lastVal);
                valToIdx.put(lastVal, idx);
    
                nums.remove(nums.size() - 1);
                valToIdx.remove(val);
                return true;
            }
            return false;
        }
    
        /** Get a random element from the set. */
        public int getRandom() {
            return nums.get(rand.nextInt(nums.size()));
        }
    }
    

    The idea comes from this problem from leetcode.com.

    0 讨论(0)
  • 2020-11-30 04:16

    A good answer depends slightly on the circumstances, in particular how often you need to get a random key for a given map (N.B. the technique is essentially the same whether you take key or value).

    • If you need various random keys from a given map, without the map changing in between getting the random keys, then use the random sampling method as you iterate through the key set. Effectively what you do is iterate over the set returned by keySet(), and on each item calculate the probability of wanting to take that key, given how many you will need overall and the number you've taken so far. Then generate a random number and see if that number is lower than the probability. (N.B. This method will always work, even if you only need 1 key; it's just not necessarily the most efficient way in that case.)
    • The keys in a HashMap are effectively in pseudo-random order already. In an extreme case where you will only ever need one random key for a given possible map, you could even just pull out the first element of the keySet().
    • In other cases (where you either need multiple possible random keys for a given possible map, or the map will change between you taking random keys), you essentially have to create or maintain an array/list of the keys from which you select a random key.
    0 讨论(0)
提交回复
热议问题