Java 将地图中的数字混洗并选择一个。

Java 将地图中的数字混洗并选择一个。,java,algorithm,random,Java,Algorithm,Random,我有一组从1到5的固定数字。这些将添加到地图中,如下所示: map.put(1, 1); map.put(2, 2); map.put(3, 3); map.put(4, 4); map.put(5, 5); public static void randArray(int[] arr, int pickHowMany) { //error checking if(pickHowMany > arr.length()) return; int temp, i

我有一组从1到5的固定数字。这些将添加到地图中,如下所示:

map.put(1, 1);
map.put(2, 2);
map.put(3, 3);
map.put(4, 4);
map.put(5, 5);
public static void randArray(int[] arr, int pickHowMany) {
   //error checking
   if(pickHowMany > arr.length())
      return;
   int temp, index;
   Random rand = new Random();
   for (int i = 0; i < pickHowMany; i++){
      index = rand.nextInt(arr.length - i) + i;
      temp = arr[i];
      arr[i] = arr[index];
      arr[index] = temp;
   }
}
从中我随机抽取两个数字,从地图上删除,留下三个数字

map.remove(Rwiner);
map.remove(Rsec);

这会给我留下三个数字,比如2,1,4。我想从中选出一个随机数。我该怎么办?

您是否在问如何在Java中选择范围为1..5的三个不同的随机整数

创建一个值为1、2、3、4、5的列表,然后调用Collections.shuffle,然后只查看前三个元素,怎么样

源代码:


也许是这样的:

// Setup
Map<Integer, Integer> map = new HashMap<Integer, Integer>();

map.put(1, 1);
map.put(2, 2);
map.put(3, 3);
map.put(4, 4);
map.put(5, 5);

int Rwiner = 3, Rsec = 5;

map.remove(Rwiner);
map.remove(Rsec);

// Get random entry from current map.
Random rnd = new Random();
int randomIndex = rnd.nextInt(map.size());
int randomKey = new ArrayList<Integer>(map.keySet()).get(randomIndex);
System.out.printf("Random entry: %d -> %d", randomKey, map.get(randomKey));

呃,据我所知,你需要继续从你的地图上随机删除一个数字。我认为数组更适合您的任务

Step 1: Convert map into an array. i.e. use values() and toArray().    
Step 2: Use map.size() as the upper bounds on nextInt(int n) on a Random 
        object.    
Step 3: Use the value from step 2 to find the corresponding index of the 
        randomly selected value on the array generated in step 1.
但是,每次随机删除对象时,都必须重复这些步骤,因此,每次都要继续创建一个新数组,或者按照aioobe的建议,需要继续将设置的值复制到arraylist中,这是一种浪费。让我们看看是否可以仅使用一个阵列而不是每次创建一个新阵列来更有效地执行此操作:

例如:

因此,上述方法更有效,因为数组知道前k个元素是死的。实施情况如下:

map.put(1, 1);
map.put(2, 2);
map.put(3, 3);
map.put(4, 4);
map.put(5, 5);
public static void randArray(int[] arr, int pickHowMany) {
   //error checking
   if(pickHowMany > arr.length())
      return;
   int temp, index;
   Random rand = new Random();
   for (int i = 0; i < pickHowMany; i++){
      index = rand.nextInt(arr.length - i) + i;
      temp = arr[i];
      arr[i] = arr[index];
      arr[index] = temp;
   }
}
因此,上面的方法更有效,因为它在同一个数组上工作,而不是每次都创建一个新的arraylist数组。另外,您还可以通过更改pickHowMany参数来拾取多个数字-该方法在上运行。请注意,它适用于数组,所以只需将地图转换为数组一次


Ray的解决方案也很好,但如果每次都要选择一个,即^2上的,则洗牌效率很低。但是,如果您只洗牌一次,Ray的解决方案将以On运行,随后您可以从列表中选择所需的数字。因此,对于多个数字,这同样是一个问题,尽管遍历列表删除前n个数字比选择数组的前n个数字要麻烦得多。

@downvorters请留下评论。。。谢谢你被否决了,因为你的问题不清楚,而且因为你的英语使用不好,很难理解你的意思。@Ben:如果是这样,我不赞成。人们不应该因为英语不流利而被否决。我对这个问题做了一些编辑。希望它能反映您在@Siten所问的问题,并帮助您在将来提高问题的质量。我有个问题。你只需要一次删除一个随机数,还是必须在第一步删除两个随机数?我想选一个数字。。。我不认为他想要三个数字…投票率更高。我喜欢使用API的替代解决方案。@James我喜欢创造性地使用API。不幸的是,每次洗牌都是以线性时间运行的。这意味着,如果要删除多个数字,此解决方案将在^2上运行。我的答案是肯定的。@Dhruv Gairola:你说得对。复杂性会更高。它希望交换数据库表中的所有记录,而不是选择一个随机id。@James、@Dhruv、@aioobe-Collections.shuffle确实以线性时间运行,它在源代码中明确说明了这一点:。等待@Siten的回答。如果他只想要一个结果,那么有一个O1解决方案称为random.nextInt5+1:-向上投票。以下是有关如何生成随机数的一些附加信息: