First, you should use generic collections:
Map<Integer, List<Integer>> map = new LinkedHashMap<Integer, List<Integer>>();
Since this looks like homework, I try to give hints to help you forward, rather than a full solution. StackOverflow is not supposed to write your homework for you :-)
You need the keys of the two elements to swap. Once you have that, you just need to get the values corresponding to the given keys and swap them between the two keys. Then add the random key generation - improving on @Eyal's generic solution:
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);
}
}
I think this solution may be faster than his even as it is. However, if you swap values within the same map many times without changing the map otherwise (i.e. no keys are added, removed or changed in the map), you can further optimize the solution by reusing the keys
array between subsequent swap calls:
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);
}
}
As you see, MapSwapper2
objects are associated with a specific map instance, whose elements they can repeatedly swap. The resetKeys
method should be called if the map keys have changed. The swapper can detect if the size of the map has changed, but not if e.g. a key has been removed and another key added.