RandomUtil.getLotteryArray - 彩票数组

无重复值等概率随机数组(蹩脚的称呼) - 彩票数组(我的称呼) 的一个高效实现算法。
import java.util.Arrays;
import java.util.Random;

/**
 * RandomUtil - Random Tool Class.
 * @author SageZk(张长弓)
 * @version 1.3
 */
public class RandomUtil {

    private RandomUtil() { /*禁止创建此类的实例*/ }

    private static volatile Random rnd = null;  //随机数发生器 1.3 加上了 volatile

    /**
     * 初始化随机数发生器。
     */
    private static synchronized void initRnd() {
        if (rnd == null) rnd = new Random();  //1.2 提高了多线程访问的安全性
    }

    /**
     * 计算并返回无重复值的以 min 为下限 max 为上限的
     * 随机整数数组。其中 min ~ max 之间整数被抽中的概率相等。
     * @param min 随机整数下限(包含)
     * @param max 随机整数上限(包含)
     * @param len 结果数组长度
     * @return 结果数组
     */
    public static int[] getLotteryArray(int min, int max, int len) {
        //参数校验及性能优化
        if (len < 0) return null;  //长度小于 0 的数组不存在
        if (len == 0) return new int[0];  //返回长度为 0 的数组
        if (min > max) {  //校正参数 min max
            int t = min;
            min = max;
            max = t;
        }
        final int LEN = max - min + 1;  //种子个数
        if (len > LEN) return null;  //如果出现 35 选 36 的情况就返回 null
        //Bug#1: if (len == 1) return new int[] {min};  //即 min == max 的情况
        //Bug#1: 1.1 版本修复
        //计算无重复值随机数组
        //1.2 提高了多线程访问的安全性和性能
        if (rnd == null) initRnd();  //初始化随机数发生器
        int[] seed = new int[LEN];  //种子数组
        for (int i = 0, n = min; i < LEN;) seed[i++] = n++;  //初始化种子数组
        for (int i = 0, j = 0, t = 0; i < len; ++i) {
            j = rnd.nextInt(LEN - i) + i;
            t = seed[i];
            seed[i] = seed[j];
            seed[j] = t;
        }
        return Arrays.copyOf(seed, len);  //注意:copyOf 需要 JRE1.6
    }

    //Unit Testing
    public static void main(String[] args) {
        final int N = 10000;  //测试次数
        for (int i = 0; i < N; ++i) {
            int[] la = RandomUtil.getLotteryArray(1, 35, 7);
            if (la == null) continue;
            for (int v : la) System.out.printf("%0$02d ", v);
            System.out.println();
        }
    }

}
  • 1
    点赞
  • 0
    收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
©️2022 CSDN 皮肤主题:大白 设计师:CSDN官方博客 返回首页
评论

打赏作者

sagezk

你的鼓励将是我创作的最大动力

¥2 ¥4 ¥6 ¥10 ¥20
输入1-500的整数
余额支付 (余额:-- )
扫码支付
扫码支付:¥2
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、C币套餐、付费专栏及课程。

余额充值