まず、ジェネリック コレクションを使用する必要があります。
Map<Integer, List<Integer>> map = new LinkedHashMap<Integer, List<Integer>>();
これは宿題のように見えるので、完全な解決策ではなく、前進するのに役立つヒントを提供しようとしています. StackOverflow は宿題を書いてくれるわけではありません :-)
交換するには、2 つの要素のキーが必要です。それができたら、指定されたキーに対応する値を取得し、2 つのキー間でそれらを交換するだけです。次に、ランダムキー生成を追加します-@Eyalの一般的なソリューションを改善します:
class MapSwapper1 {
private static Random rnd = new Random();
private static K[] nullArray = new K[0];
public static <K,V> void swapTwoRandomValues(Map<K,V> map){
if (map.size() <= 1)
throw new IllegalArgumentException("Not enough items");
//Choose 2 random positions pos1<pos2
int pos1 = 0, pos2 = 0;
while (pos1 == pos2) {
pos1 = rnd.nextInt(map.size());
pos2 = rnd.nextInt(map.size());
}
// Get the keys into an indexable array
K[] keys = map.keySet().toArray(nullArray);
swap(map, keys[pos1], keys[pos2]);
}
private static void <K,V> swap(Map<K, V> map, K key1, K key2) {
V tmp = map.get(key1);
map.put(key1, map.get(key2));
map.put(key2, tmp);
}
}
この解決策は、そのままでも彼よりも速いかもしれないと思います。ただし、マップを変更せずに同じマップ内で値を何度もスワップする場合 (つまり、マップでキーが追加、削除、または変更されていない場合)、keys
後続のスワップ呼び出し間で配列を再利用することにより、ソリューションをさらに最適化できます。
class MapSwapper2<K, V> {
private Random rnd = new Random();
private Map<K,V> map;
private K[] keys;
public MapSwapper2(Map<K, V> map) {
resetKeys();
this.map = map;
}
public void resetKeys() {
if (map.size() <= 1)
throw new IllegalArgumentException("Not enough items");
keys = map.keySet().toArray(new K[0]);
}
public void swapTwoRandomValues() {
if (map.size() != keys.length)
resetKeys();
//Choose 2 random positions pos1<pos2
int pos1 = 0, pos2 = 0;
while (pos1 == pos2) {
pos1 = rnd.nextInt(map.size());
pos2 = rnd.nextInt(map.size());
}
swap(map, keys[pos1], keys[pos2]);
}
private void swap(K key1, K key2) {
V tmp = map.get(key1);
map.put(key1, map.get(key2));
map.put(key2, tmp);
}
}
ご覧のとおり、MapSwapper2
オブジェクトは特定のマップ インスタンスに関連付けられており、その要素は繰り返し交換できます。マップ キーが変更された場合は、このresetKeys
メソッドを呼び出す必要があります。スワッパーは、マップのサイズが変更されたかどうかを検出できますが、たとえば、キーが削除されて別のキーが追加された場合は検出できません。