Java里随机数主要是通过Math.random方法和java.util.Random类来生成,当然也有借助System.currentTimeMillis()生成的,甚至如果你高兴,完全可以自己写个方法来生成。
一、java.util.Random类
1.伪随机数
Random类实现的是有规则的随机,也就是伪随机。Java随机数是通过线性同余公式产生的,也就是说通过一个复杂的算法生成的。只要这个随机数是由确定算法生成的,那就是伪随机,只能通过不断算法优化,使所谓的随机数更接近随机。但其实随机这个属性和算法本身就是矛盾的,通过真实随机事件取得的随机数才是真随机数。
2.伪随机数的不安全性
Java自带的随机数函数是很容易被黑客破解的,因为黑客可以通过获取一定长度的随机数序列来推出你的seed,然后就可以预测下一个随机数。
3.Java中随机数的种子
种子就是产生随机数的第一次使用值,机制是通过一个函数,将这个种子的值转化为随机数空间中的某一个点上,并且产生的随机数均匀的散布在空间中。以后产生的随机数都与前一个随机数有关。
Java中的随机数种子若不填写就会使用缺省值,即系统时间。不用种子的不随机性会增大。
4.java.util.Random类的构造方法
4.1 public Random()
该构造方法使用一个和当前系统时间对应的相对时间有关的数字作为种子数,然后使用这个种子数构造Random对象。
4.2 public Random(long seed)
该构造方法可以通过给定的种子进行创建。
如下代码所示:
1 2 |
Random r =new Random(100); System.out.println(r.nextInt(20)); |
种子数只是随机算法的起源数字,和生成的随机数字的区间没有任何关系。
初始化时100并没有起直接作用(注意:不是没有起作用),r.nextInt(20)中的20是随机数的上限,产生的随机数为0-20的整数,不包括20。
5.java.util.Random类的方法
Random类里维护了一个随机数生成器序列,类似一个数组,里面存着生成好的随机数。
- int next(int bits):生成下一个伪随机数,参数bits是位数。
- boolean nextBoolean():返回下一个伪随机数,它是取自此随机数生成器序列的均匀分布的boolean值,生成true和false的值几率相等。
- void nextBytes(byte[] bytes):生成随机字节并将其置于用户提供的 byte 数组中。
- double nextDouble():返回下一个伪随机数,它是取自此随机数生成器序列的、在0.0和1.0之间均匀分布的 double值,不包括1.0
- float nextFloat():同上,但类型为Float
- double nextGaussian():返回下一个伪随机数,它是取自此随机数生成器序列的、呈高斯(“正态”)分布的double值,其平均值是0.0标准差是1.0。
- int nextInt():返回下一个伪随机数,它是此随机数生成器的序列中均匀分布的 int 值,该值介于int的区间,也就是-231到231-1之间。
- int nextInt(int n):返回一个伪随机数,它是取自此随机数生成器序列的、该值介于[0,n)的区间,也就是0到n,不包括n。
- long nextLong():返回下一个伪随机数,它是取自此随机数生成器序列的均匀分布的 long 值。
- void setSeed(long seed):使用单个 long 种子设置此随机数生成器的种子。
记住常用的几个即可。
6.Random类生成随机数使用示例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 |
public static void main(String[] args) { Random r = new Random(); // 生成[0,1.0)区间的小数,直接使用nextDouble方法获得 double d1 = r.nextDouble(); // 生成[0,5.0)区间的小数 // 同理,生成[0,d)区间的随机小数,d为任意正的小数,则只需要将nextDouble方法的返回值乘以d即可。 double d2 = r.nextDouble() * 5; // 生成[1,2.5)区间的小数,同理,生成任意非从0开始的小数区间[d1,d2)范围的随机数字(其中d1不等于0),则只需要首先生成[0,d2-d1)区间的随机数字,然后将生成的随机数字区间加上d1即可。 double d3 = r.nextDouble() * 1.5 + 1; // 生成任意整数,直接使用nextInt方法即可 int n1 = r.nextInt(); // 获取随机的boolean值 boolean b = r.nextBoolean(); // 获取随机的数组buf[] byte[] buf = new byte[1024]; r.nextBytes(buf); // 获取随机的float值,范围[0.0, 1.0) float f = r.nextFloat(); // 获取随机的[0,100)之间的int值 int i2 = r.nextInt(100); // 获取随机的高斯分布的double值 double g = r.nextGaussian(); // 获取随机的long值 long l = r.nextLong(); } |
二、Math.random()
其实看源码就知道,该方法内部其实是调用的java.util.Random类的nextDouble()方法。

它返回的是0(包含)到1(不包含)之间的double值。使用方法如下:
1 |
double d = Math.random(); |
若要获取int类型的整数,只需要将上面的结果转行成int类型即可。比如,获取[0, 100)之间的int整数。方法如下:
1 2 |
double d = Math.random(); int i = (int)(d*100); |
三、System.currentTimeMillis()
通过System.currentTimeMillis()来获取随机数。实际上是获取当前时间毫秒数,它是long类型。使用方法如下:
1 |
long l = System.currentTimeMillis(); |
四、随机数实战示例
题目1:生成(-10,10)之间的保留小数点后两位数的随机数
解决方法:
1.java中随机数生成函数Random r=new Random(); r.nextFloat();//生成(0,1)之间的浮点型随机数。将上述随机数乘以10,得到生成(0,10)之间的随机数。
2.生成一个Boolean型的随机数用于控制数的正负:r.nextBoolean();
3.保留小数位数两位的方法:Math.floor(n*100+0.5)/100;得到的数为double型。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
public class CreateRandom { public float numRandom() { float num; Random r = new Random(); float value = (float) (Math.floor(r.nextFloat() * 1000 + 0.5) / 100); Boolean b = r.nextBoolean(); if (b) { num = value; } else { num = 0 - value; } return num; } public static void main(String[] args) { CreateRandom cr = new CreateRandom(); float num = cr.numRandom(); System.out.print(num); } } |
题目2:Java生成随机无重复随机数,使用ArrayList实现
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 |
import java.util.ArrayList; import java.util.Random; /** * 生成随机无重复随机数,使用ArrayList实现 * * 算法:加入随机数时检测列表中是否已存在此随机数,有则重来,无则加入。 * */ public class Demo { public static void main(String[] args) { int length = 50; // 50个随机数 Random random = new Random(); ArrayList<Integer> list = new ArrayList<Integer>(); for (int i = 0; i < length; i++) { int number = random.nextInt(100) + 1; // 1-100的随机数(此处100必须比length大,否则会死循环) if (!list.contains(number)) { list.add(number); } else { i--; // 保证生成的随机数个数足够,防止有重复随机数时造成空位 } } for (int i = 0; i < length; i++) { System.out.print(list.get(i) + "\t"); if ((i + 1) % 10 == 0) { System.out.println(""); } } } } |
题目3:java生成固定位数的密码随机数代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 |
public class RandomPassword { /** * @param args */ public static void main(String[] args) { System.out.println(genRandomNum(10)); } /** * 生成随即密码 * * @param pwd_len * 生成的密码的总长度 * @return 密码的字符串 */ public static String genRandomNum(int pwd_len) { // 35是因为数组是从0开始的,26个字母+10个数字 final int maxNum = 36; int i; // 生成的随机数 int count = 0; // 生成的密码的长度 char[] str = { 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9' }; StringBuffer pwd = new StringBuffer(""); Random r = new Random(); while (count < pwd_len) { // 生成随机数,取绝对值,防止生成负数, i = Math.abs(r.nextInt(maxNum)); // 生成的数最大为36-1 if (i >= 0 && i < str.length) { pwd.append(str[i]); count++; } } return pwd.toString(); } } |
题目4:Java生成带权重的随机数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 |
import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Random; //带权重的随机数 //面试的时候面试官问道一个这样的问题 //A、B、C三个字符分别出现的概率是30%,40%,30% //分析:首先1-100随机产生一个数,判断这个数,1-30出现的概率是30%, 31—70出现的概率是40%, 71-100出现的概率是30% public class WeightRandom { public static void main(String[] args) { Random ran = new Random(); String str=getWanfei(ran.nextInt(100)); Map<String,Object> map = new HashMap<String,Object>(); map.put("key","A"); map.put("value","30"); Map<String,Object> map1 = new HashMap<String,Object>(); map.put("key","B"); map.put("value","70"); List<Map<String,Object>> list = new ArrayList<Map<String,Object>>(); list.add(map); list.add(map1); System.out.println( getWeight(list,ran.nextInt(100))); } //知道权重的情况下 public static String getWanfei(int num){ if(num>=1 && num<=30){ return "A"; }else if(num>=31 && num<70){ return "B"; }else{ return "C"; } } //如果A、B、C的个数不确定 ,权重的总数也也不确定 public static String getWeight(List<Map<String,Object>> list,int ran){ //map里放的是a,b,c 值,和每个a、b、c对应的权重 int sum=0; int total = list.size(); for(int i=0;i<total;i++){ sum+=Integer.parseInt(list.get(i).get("value").toString()); if(ran<=sum){ return list.get(i).get("key").toString(); } } return null; } } |