1

我有一个linkedhashmap,我需要在2个随机值之间置换(更改值的键)

例子 :

键 1 值 123 键 2 值 456 键 3 值 789

随机排列 2 个值后

键 1 值 123 键 2 值 789 键 3 值 456

所以在这里我在键 2 和键 3 之间置换了值

谢谢你;

我的地图代码示例:

    Map map = new LinkedHashMap();
        map =myMap.getLinkedHashMap();

       Set key = map.keySet();

   for(Iterator it = cles.iterator(); it.hasNext();)
    {
        Integer cle =  it.next(); 
        ArrayList values = (ArrayList)map.get(cle);//an arrayList of integers

        int i = 0;
        while(i < values.size())
        {
            //i donno what to do here
            i++;
        }
    }
4

3 回答 3

2

首先,您应该使用泛型集合:

Map<Integer, List<Integer>> map = new LinkedHashMap<Integer, List<Integer>>();

由于这看起来像家庭作业,因此我尝试提供提示以帮助您前进,而不是完整的解决方案。StackOverflow 不应该为你写作业:-)

您需要交换两个元素的键。一旦你有了它,你只需要获取与给定键对应的值并在两个键之间交换它们。然后添加随机密钥生成 - 改进 @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如果映射键已更改,则应调用该方法。交换器可以检测映射的大小是否已更改,但不能检测例如已删除键并添加了另一个键。

于 2010-05-07T22:09:37.830 回答
1

由于这不是家庭作业,因此这是我的解决方案。交换本身是有效的,但可以改进 2 个项目的随机抽样 :)

private static Random rnd = new Random();
...
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());
    }       
    if (pos1 > pos2){
        int aux = pos1;
        pos1 = pos2;
        pos2 = aux;
    }

    //Fetch the entries
    Iterator<Map.Entry<K, V>> it = map.entrySet().iterator();
    Map.Entry<K, V> entry1 = null;
    for(int i=0;i <= pos1;i++)
        entry1 = it.next();
    Map.Entry<K, V> entry2 = null;
    for(int i = pos1;i < pos2;i++)
        entry2 = it.next();

    //Swap values
    V tmpValue = entry1.getValue();
    entry1.setValue(entry2.getValue());
    entry2.setValue(tmpValue);
}
于 2010-05-07T22:23:03.323 回答
1

注意到一些人已经输入了一些东西,但这是相当完整的,它不是最有效的代码,但它会帮助你,并将值放回地图中。

    Map<Integer, Integer> map = new LinkedHashMap<Integer, Integer>();
    map.put(1, 123);
    map.put(2, 456);
    map.put(3, 789);

    for (Entry<Integer, Integer> entry : map.entrySet())
        System.out.println("old key: " + entry.getKey() + " and value: " + entry.getValue());

    List<Integer> values = new ArrayList<Integer>(map.values());
    Collections.shuffle(values);

    int i = 0;
    for (Entry<Integer, Integer> entry : map.entrySet())
    {
        map.put(entry.getKey(), values.get(i));
        i++;
    }

    for (Entry<Integer, Integer> entry : map.entrySet())
        System.out.println("new key: " + entry.getKey() + " and value: " + entry.getValue());
于 2010-05-07T22:28:21.660 回答