HashMap: iterating the key-value pairs in random order

后端 未结 3 819
误落风尘
误落风尘 2021-01-18 03:43

I have a HashMap and I\'d like to iterate they key-value pairs in a different random order each time i get the iterator. Conceptually I\'d like to \"shuffle\" the map before

相关标签:
3条回答
  • 2021-01-18 04:21

    Try use concurent hash map and get key by random before iteration cycle

    Map<String, String> map = Maps.newConcurrentMap();
    
            map.put("1", "1");
            map.put("2", "2");
            Iterator<String> iterator = map.keySet().iterator();
            while (iterator.hasNext()) {
                map.remove("2");// add random key values
                map.put("2", "2");
                String next = iterator.next();
                System.out.println("next" + next);
            }
    

    Random remove/put values can "shuffle" your map

    0 讨论(0)
  • 2021-01-18 04:27

    Reshuffling a large collection is always going to be expensive. You are going to need at least one reference per entry. e.g. for 1 million entries you will need approx 4 MB.

    Note; the shuffle operation is O(N)

    I would use

    Map<K,V> map = 
    List<Map.Entry<K,V>> list = new ArrayList<Map.Entry<K,V>>(map.entrySet());
    
    // each time you want a different order.
    Collections.shuffle(list);
    for(Map.Entry<K, V> entry: list) { /* ... */ }
    
    0 讨论(0)
  • 2021-01-18 04:39

    Actually you do not need to shuffle at all:
    Just draw a random index in an array of keys and remove the key by overwritting with the last:

    public class RandomMapIterator<K,V> implements Iterator<V> {
    
    private final Map<K,V> map;
    private final K[] keys;
    
    private int keysCount;
    
    @SuppressWarnings("unchecked")
    public RandomMapIterator(Map<K,V> map) {
        this.map = map;
        this.keys = (K[]) map.keySet().toArray();
        this.keysCount = keys.length;
    }
    
    @Override
    public boolean hasNext() {
        return keysCount!=0;
    }
    
    @Override
    public V next() {
        int index = nextIndex();
        K key = keys[index];
        keys[index] = keys[--keysCount];
        return map.get(key);
    }
    
    protected int nextIndex() {
        return (int)(Math.random() * keysCount);
    }
    
    @Override
    public void remove() {
        throw new UnsupportedOperationException();
    }
    

    }

    0 讨论(0)
提交回复
热议问题