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>一位java技术达人的成长历程(四年)

打个比方吧,这位牛人23岁毕业,做了两年嵌入式C编程,25岁时,突然对Java的优雅设计情有独钟,而正好这时,公司有个Java项目,Java技术之旅开始了。  1、最开始三个月,开始接触Java,比...
  • xiu2016
  • xiu2016
  • 2016年10月20日 01:41
  • 154

Java设计模式——合成/聚合复用原则

一、什么是合成/聚合复用原则? 合成/聚合复用原则是在一个新的对象里面使用一些已有的对象,使之成为新对象的一部分;新的对象通过向这些对象的委派达到复用已有功能的目的。 简述为:要尽量使用合成/聚合,尽...

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

在项目中遇到客户一个需求,ID的生成策略:长度8位,用户在知道自己的ID(如:10000018)后,不能通过ID来推测相关信息,如用户可能推测我是第18个注册用户,上一个注册用户的ID是1000001...

Java实现生成n个不重复的随机数

需求:根据min和max,生成n个不重复的随机数。(注:范围[min,max],n

算法--生成m个指定范围的不重复随机数的三种方法分析(Java实现)

Q题目如何产生m个在0-N范围内的无重复的随机数(不包含N)

java生成不重复的随机数【某个范围0-10】或者【某个数组int[1,3,56,14,26,22,17]】

【java】废话不多说直接贴代码: /** * 随机指定范围内N个不重复的数 * 最简单最基本的方法 * @param min 指定范围最小值 * @param max 指定...
  • xb12369
  • xb12369
  • 2015年03月27日 11:36
  • 3132

java 生成一组不重复的随机数

引出这个问题的是,是我在学习设计拼图游戏中出现的,拼图游戏开始的时候,图是散乱的,比如拼图游戏被分成了8*4 共32块,那么32块图对应着32个数,而若要使每次开始前的排列顺序不一致,就需要产生32个...
  • nufangn
  • nufangn
  • 2016年01月18日 21:10
  • 894

高效产生一组不重复的随机数(受编程珠矶启示)java实现

高效产生一组不重复的随机数这个需求应该是很常见的吧,需要从 0 到 n 之间选 k 个不重复的数组成一个序列。算法复杂度O(n),受编程珠矶启示,我用java写了该算法的实现,由于时间比较紧,其他的以...

自己写的java产生不重复随机数

  • 2014年03月05日 09:24
  • 702B
  • 下载

vb.net控制台 random类 随机字符,随机数 (生成4个随机3位数倒序输出)

编译环境vb.net vb控制台应用程序   题目要求: 随机生成一定范围的字符 随机生成一定范围的数字 查找输出一段字符串第n个位置后的m位字符(字符串长度不能低于n+m) 随机生成...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:Java 生成任意位数永不重复的随机数策略实现
举报原因:
原因补充:

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