每篇一句
稍待秋风凉冷后, 高寻白帝问真源.《望岳三首. 其二》- 唐代 - 杜甫
获取随机数的方式
经常使用的大概就下面 5 种
1Math.random(): 获取随机小数范围:[0.0,1.0) 返回的值是 double 类型
2Random 类
构造方法: Random() : 建议使用无参构造方法
方法: int nextInt(int n) : 获取 [0,n) 范围的随机整数
3ThreadLocalRandom (jdk1.7 开始出现)
创建对象: static ThreadLocalRandom current()
方法: int nextInt(int a,int b) : 获取 [a,b) 范围的随机整数
4System.currentTimeMillis(): 获取一个当前时间毫秒数的 long 型数字.
5UUID 类
静态方法: static UUID randomUUID(): 获取类型 4(伪随机生成的)UUID 的静态工厂. 使用加密的强伪随机数生成器生成该 UUID. 即获取随机的字符串, 该字符串每次获取都不会重复
- ___
- 1Math.random()
1, 在 j2se 中使用 Math.random()令系统随机选取一个 0~1 之间的 double 类型小数, 将其乘以一个数, 比如 25, 就能得到一个 [0,25) 范围内的随机数; Math.round()是四舍五入的意思
- // 获取一个[min,max] 区间内的随机整数
- int randomNumber = (int) Math.round(Math.random()*(max-min)+min);
2Random 类
使用 java.util.Random 类来产生一个随机数发生器, 这个也是我们在 j2me 的程序里经常用的一个取随机数的方法. 它有两种形式的构造函数, 分别是 Random()和 Random(long seed).Random()使用当前时间即 System.currentTimeMillis()作为发生器的种子, Random(long seed)使用指定的 seed 作为发生器的种子. 随机数发生器 (Random) 对象产生以后, 通过调用不同的 method:nextInt(),nextLong(),nextFloat(),nextDouble()等获得不同类型随机数. 如果两个 Random 对象使用相同的种子(比如都是 25), 并且以相同的顺序调用相同的函数, 那它们返回值完全相同.
- // 获取一个 [min,max] 区间内的随机整数
- Random random = new Random();
- int randomNumber = random.nextInt(max)%(max-min+1) + min;
- 3ThreadLocalRandom
在多线程下, 使用 java.util.Random 产生的实例来产生随机数是线程安全的, 但深挖 Random 的实现过程, 会发现多个线程会竞争同一 seed 而造成性能降低. ThreadLocalRandom 是一个可以独立使用的, 用于生成随机数的类. 继承自 Random, 但性能超过 Random, 所谓 "青出于蓝而胜于蓝". 其 API 所提供方法, 不多, 父类 Random 具有的, 它也一样具有.
多线程下获取 [1,100) 的随机数, 如下代码
- import java.util.concurrent.ThreadLocalRandom;
- public class ThreadLocalRandomDemo {
- public static void main(String[] args) {
- for (int i = 0; i <10; i++) {
- new Player().start();
- }
- }
- private static class Player extends Thread {
- @Override
- public void run() {
- System.out.println(getName() + ":" + ThreadLocalRandom.current().nextInt(1,100));
- }
- }
- }
切记:
任何情况下都不要在多个线程间共享一个 Random 实例, 而该把它放入 ThreadLocal 之中
我在另外一篇博客中将详细介绍 ThreadLocalRandom, 想了解可以移步这里:
- ___
- 4System.currentTimeMillis()
在 System 类中有一个 currentTimeMillis()方法, 这个方法返回从 1970 年 1 月 1 号 0 点 0 分 0 秒到目前的一个 long 型的毫秒数, 可作为一个随机数, 还可以将其对某些数取模, 就能限制随机数的范围; 此方式在循环中同时产生多个随机数时, 会是相同的值, 有一定的局限性!
- // 获取一个 [min,max] 区间内的随机整数
- long randomNum = System.currentTimeMillis();
- int randomNumber = (int) randomNum%(max-min+1)+min;
5UUID 类
UUID 是指 Universally Unique Identifier, 翻译为中文是通用唯一识别码, 其目的, 是让分布式系统中的所有元素, 都能有唯一的辨识信息.
据说世界可以为世界的每一粒沙子分配一个 UUID, 还不会重复
输入的格式是: UUID 的十六个八位字节被表示为 32 个十六进制数字, 以连字号分隔的五组来显示, 形式为 8-4-4-4-12, 总共有 36 个字符(即三十二个英数字母和四个连字号). 例如: 123e4567-e89b-12d3-a456-426655440000
使用很简单, 如下即可
String uuid = UUID.randomUUID().toString()
最后, 补充一个随机指定范围内 N 个不重复的数的实现方法
- /**
- * 随机指定范围内 N 个不重复的数
- * 利用 HashSet 的特征, 只能存放不同的值
- * @param min 指定范围最小值
- * @param max 指定范围最大值
- * @param n 随机数个数
- * @param HashSet<Integer> set 随机数结果集
- */
- public static void randomSet(int min, int max, int n, HashSet<Integer> set) {
- if (n> (max - min + 1) || max < min) {
- return;
- }
- for (int i = 0; i < n; i++) {
- // 调用 Math.random()方法
- int num = (int) (Math.random() * (max - min)) + min;
- set.add(num);// 将不同的数存入 HashSet 中
- }
- int setSize = set.size();
- // 如果存入的数小于指定生成的个数, 则调用递归再生成剩余个数的随机数, 如此循环, 直到达到指定大小
- if (setSize < n) {
- randomSet(min, max, n - setSize, set);// 递归
- }
- }
来源: http://www.bubuko.com/infodetail-3325653.html