7

HashMap があり、イテレータを取得するたびにキーと値のペアを異なるランダムな順序で反復処理したいと考えています。概念的には、イテレータを呼び出す前にマップを「シャッフル」したいと思います (または、必要に応じてイテレータを「シャッフル」します)。

私が見る2つのオプションがあります:

1) LinkedHashMap のアプローチを使用し、エントリのリストを内部的に保持し、その場でシャッフルし、イテレータが呼び出されたときにそのビューを返します。
2) map.entrySet() を取得し、ArrayList を作成して、shuffle() を使用します。

2 つのアプローチは非常に似ているように見えますが、私は非常に大きな HashMap を期待しているので、メモリや計算を無駄にする立場にないので、詳細と内部に本当に関心があります。

4

3 に答える 3

0

実際には、シャッフルする必要はまったくありません。
キーの配列にランダムなインデックスを描画し、最後に上書きしてキーを削除するだけです。

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();
}

}

于 2012-10-10T10:53:39.843 に答える