在每次通话时生成唯一的随机数

Anu*_*Jha 3 java arrays random collections

在一次采访中,我被要求提供一种方法,每次调用它时都会生成唯一的5位数随机数.例如:如果我调用方法得到22222,那么在下次通话中我不应该得到22222.

我写了一个代码如下:

import java.util.ArrayList;
import java.util.Collections;
import java.util.Scanner;

public class RandomNumberGen {


    private static ArrayList arr=new ArrayList();
    private static int k=-1;
    public RandomNumberGen(){
        for (int i=10000;i<99999;i++){
            arr.add(i);
        }
        Collections.shuffle(arr);
    }
    public static void main(String[] args) {
        for(int m=0;m<10;m++){
            try {
                System.out.println(new RandomNumberGen().randomNumbermethod());
            } catch (Exception e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }


    }
    public Integer randomNumbermethod() throws Exception{
        k++;
        if(k>=arr.size()){
            throw new Exception("No more number available");
        }else return (Integer) arr.get(k);
    }

}
Run Code Online (Sandbox Code Playgroud)

答案被接受但我被要求现在避免记忆浪费.我的问题在这里,因为你可以看到我只使用了10个数字.所以arraylist占用的剩余空间是一个记忆 - 浪费.有一种方法我可以实现同样的事情而不需要额外的记忆.我的意思是在某种程度上使用哪个唯一编号可以在每次调用时生成,这样就不会浪费这么多内存.

Pio*_*ler 6

private static int number = 10000;
public int getNextUniqueRandomNumber() {
   return number++;
}
Run Code Online (Sandbox Code Playgroud)

随机数发生器


Pet*_*ser 6

启示:

  • 为了不再返回相同的值,您需要跟踪已生成的数字.这可能非常耗费内存.
  • 你最终用完了数字.您不必继续搜索未使用的随机数,而是可以跟踪您返回的号码数量(或者仍有多少号码可用)并识别您是否用完了数字.

可以在集合(集合)中跟踪生成的数字.这意味着每个数字的开销为32位(当跟踪可用或生成的数字时)加上收集开销.另一种可能性是使用布尔数组并标记已使用的插槽.同样,这是一个开销,因为布尔值通常存储为32位值.
但是存在一种更便宜的存储布尔值的方法:作为整数的打包位.这是什么java.util.BitSet,所以每个布尔将占用一位.

解决方案BitSet并跟踪可用的数量:

public class RandomNumbers {

    private final Random random = new Random();
    private final BitSet used = new BitSet();
    private final int min = 10000;
    private final int max = 99999;
    private final int numbersAvailable = max - min + 1;

    public static void main (String[] args) {

        RandomNumbers randomNumbers = new RandomNumbers();
        for (int i = 0; i < 100; i++) {
            System.out.println(randomNumbers.nextRandom());
        }
    }

    public int nextRandom () throws NoSuchElementException {

        while (numbersAvailable > 0) {
            int rnd = min + random.nextInt(max - min + 1);
            if (!used.get(rnd)) {
                used.set(rnd);
                numbersAvailable--;
                return rnd;
            }
        }
        throw new NoSuchElementException();
    }
}
Run Code Online (Sandbox Code Playgroud)


Pio*_*ler 5

只是

(int)(Math.random()*89999)+10000
Run Code Online (Sandbox Code Playgroud)

编辑后:(在编辑之前没有理解) - 你可以HashSet在随机中和之后放入生成的数字,只检查是否包含新数字(如果你多次使用它会很慢,但我认为这是一个很好的解决方案,如果你不需要很多数字.

从我的评论:在大约50%的数字超出后,我会创建一个剩余数字的集合,与你的相同,但你应该在课堂上记录,它可以在50%的结果使用后冻结片刻,并提供设置的能力这个因素给客户.

也许是一种更好的方法,取决于生成数字中必须有多少"随机性"(例如序列生成器的数学方法)