Java 生成任意位数永不重复的随机数策略实现

原创 2017年02月10日 14:52:58

在项目中遇到客户一个需求,ID的生成策略:长度8位,用户在知道自己的ID(如:10000018)后,不能通过ID来推测相关信息,如用户可能推测我是第18个注册用户,上一个注册用户的ID是10000017,这样就不能很好的保护账号安全了,可以凭证推测数据来进行不法之事。

经过网上查找和思考,便有了如下的解决方案:

  • 生成一个装有1-99999999数值的数组
  • 将数值内的值随机打乱
  • 将数值的值分开保存到不同的文件(txt)中
  • 获取ID的时候,可以随机从任意一文件中获取第一行的ID值,然后将剩余行的ID值重写写会原文件
  • 如果文件中的ID值已经取完则删除

逻辑很简单,就看实现了,代码如下:

生成ID并保存到硬盘

    /**
     * 生成1-99999999的数字编码保存到硬盘
     */
    private static void generateAppCode2Disk(){
        int begin = 1;  
        int end = 99999999;  
        int count = begin + end;  
        //生成1到99999999的所有整数  
        int[] codes = new int[count + 1];  
        for (int i = begin; i <= end; i++){  
            codes[i] = i;  
        }
        //随机交换数据  
        int index = 0;
        int tempCode = 0;
        Random random = new Random();
        for (int i = begin; i <= end; i++){  
            index = random.nextInt(count+1);  
            tempCode = codes[index];  
            codes[index] = codes[i];  
            codes[i] = tempCode;  
        }
        //生成1000个文件,每个文件包含100000个appCode
        StringBuilder sb = new StringBuilder();
        int flag = 100000;
        System.out.println("***********开始**********");
        try {
            for(int i = begin; i <= end; i++){
                sb.append(codes[i]).append("\n");
                if(i == end || i%flag == 0){
                    File folder = new File("D:/IDGenerate");
                    if(!folder.isDirectory()){
                        folder.mkdir();
                    }
                    if(i==end){
                        i = end +1;
                    }
                    File file = new File("D:/IDGenerate/ID_"+(i/flag)+".txt");
                    if (!file.exists()) {
                        file.createNewFile();
                    }
                    BufferedWriter bw=new BufferedWriter(new FileWriter(file.getAbsoluteFile()));
                    bw.write(sb.toString());
                    bw.flush();
                    bw.close();
                    sb = new StringBuilder();
                    System.out.println("当前i值:"+i+"第"+(i/flag)+"个文件生成成功!");
                }
            }
            System.out.println("***********结束**********");
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }

获取ID

    //获取唯一8位ID
    public String createAppCode(){
        BufferedWriter bw = null;
        BufferedReader br = null;
        FileReader fr = null;
        FileWriter fw = null;
        try {
            String dir = "D:/";
            if(StringUtils.isBlank(dir)){
                throw new Exception("获取文件路径为空");
            }
            File rootFile = new File(dir);
            String[] fileNames = rootFile.list();
            if(fileNames == null || fileNames.length == 0){
                throw new Exception("路径不正确,或者ID已经分配完毕,请联系管理员");
            }
            //获取第一个文件
            fr=new FileReader(dir+"/"+fileNames[0]);//获取文件流
            br = new BufferedReader(fr); //将流整体读取。
            StringBuilder sb = new StringBuilder();
            String appCode = "";
            String temp;
            int count =1;
            while(!StringUtils.isBlank(temp=br.readLine())){
                if(count == 1){
                    count++;
                    appCode = temp;
                    continue;
                }
                else{
                    sb.append(temp).append("\n");
                }

            }
            br.close();
            fr.close();
            if(!StringUtils.isBlank(appCode)){
                //判断文件内容是否还有下一行
                if(sb.length()<=0){
                    File delFile = new File(dir+"/"+fileNames[0]);
                    if(delFile.exists()){
                        delFile.delete();//删掉
                    }
                }
                else{
                    //将剩余内容重写写回文件
                    fw = new FileWriter(dir+"/"+fileNames[0]);
                    bw=new BufferedWriter(fw);
                    bw.write(sb.toString());
                    bw.flush();
                    bw.close();
                    fw.close();
                }
                String prex = "00000000";
                appCode = prex.substring(0,prex.length()-appCode.length())+appCode;
                return appCode;
            }
            else{
                throw new Exception("文件中内容为空");
            }
        } catch (Exception e) {
            log.error("获取ID error:"+e.getMessage());
            return null;
        } finally{
            try {
                if(bw != null)bw.close();
                if(br != null)bw.close();
                if(fr != null)bw.close();
                if(fw != null)bw.close();
            } catch (IOException e) {
                log.error("关闭文件流文件异常:"+e.getMessage());
            }
        }
    }

这样将生成的ID分成1000个文件保存到硬盘,取数据的时候从任意文件中取都可,这样能很好的保证了随机,不重复,而且在测试的时候发现效率还不错,内存,CPU的使用都微乎其微。

为了更好的优化获取ID效率,可以有如下改进:

  • 将ID保存到更多的文件中,这样文件的容量就可以很小,加载的时候就更快
  • 预读ID,可以提前预读50,100等数量的ID保存到list中,直接从内存取数据就更快了,不过这逻辑就复杂了很多,要保证list的数据和硬盘数据的同步,就需要更多的代码来判断了

    此文章供大家参考,大家有什么好的建议,算法都可以提出来交流的!

Java生成指定位数不重复随机数

1、以生成不重复20位随机数为例public class SerialGeneratorTest { private static final Object OBJECT = new Objec...
  • yewen1234
  • yewen1234
  • 2017年05月21日 19:50
  • 502

java产生任意范围内不重复的随机数

n:需要的随机数的数目 min:下限; max:上限 import java.util.* ; class Tester { public static void main(String arg...
  • u012566693
  • u012566693
  • 2015年06月20日 13:37
  • 1062

JAVA生成给定范围内的不重复的随机数的几种方法

在java中的Math类中存在一个random()方法,该方法默认生成0.0到1.0之间的double型随机数;经过稍微处理,就可以产生我们需要的随机数以及随机字符。 除了Math类中的random...
  • haiyoung
  • haiyoung
  • 2015年08月29日 09:59
  • 13350

java随机数生成(固定位数)

随机生成 a 到 b (不包含b)的整数: (int)(Math.random()*(b-a))+a; 随机生成 a 到 b (包含b)的整数:(int)(Math.random()*(b-a+1)...
  • lvxinzhi
  • lvxinzhi
  • 2016年02月16日 15:48
  • 1113

java中随机生成随机数及不重复的随机数字

Java中产生随机数 1 . 调用java.lang下面Math类中的random()方法产生随机数           public class MyRandom {       ...
  • u014535666
  • u014535666
  • 2015年06月18日 21:57
  • 5884

生成20个1-100不重复的随机数

思路很简单 1.创建1个长度为100的int数组作为容器,存放1-100,1个结果容器,1个标记量 2.调用随机函数得到N,用N当做数组的下标 3.通过下标取到对应的值判断是否有效,若有效,则进...
  • qinhui13
  • qinhui13
  • 2013年10月09日 00:17
  • 1917

Java生成不重复随机数UUID(转)

/**       * 生成随机数       * GUID: 即Globally Unique Identifier(全球唯一标识符) 也称作 UUID(Universally Unique  ...
  • qq_35619711
  • qq_35619711
  • 2017年05月09日 00:04
  • 4225

C#生成不重复随机数的方法

在使用Random类生成随机数时,我们可能会碰到生成随机数重复的问题。 比如我们要生成6位数字验证码,虽然也是使用Random,但是可能出现111111,999999这样的情况。 这是因为...
  • shan1774965666
  • shan1774965666
  • 2015年09月06日 18:51
  • 442

生成四位不重复随机数

using System;using System.Data;using System.Configuration;using System.Collections;using System.Web;...
  • baozhenliang
  • baozhenliang
  • 2006年11月22日 09:53
  • 990

java随机生成6/8/12位数,要求每次产生的随机数与已生成的随机数不重复

备注:如果有相同的数据,那么就重新生成一个新的数据: 后台代码如下: public static void main(String[] args) { String cardNumber=re...
  • xuanzhangran
  • xuanzhangran
  • 2017年02月23日 15:07
  • 1840
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:Java 生成任意位数永不重复的随机数策略实现
举报原因:
原因补充:

(最多只允许输入30个字)