1. 程式人生 > >Java 生成任意位數永不重複的隨機數策略實現

Java 生成任意位數永不重複的隨機數策略實現

在專案中遇到客戶一個需求,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 生成任意位數永不重複隨機數策略實現

在專案中遇到客戶一個需求,ID的生成策略:長度8位,使用者在知道自己的ID(如:10000018)後,不能通過ID來推測相關資訊,如使用者可能推測我是第18個註冊使用者,上一個註冊使用者的ID是10000017,這樣就不能很好的保護賬號安全了,可以憑證推測資料來

java生成指定範圍內的隨機數

lan this 原理 n) public exti -1 方法 這才   我們經常說Java中的隨機數是偽隨機數,那麽我們要知道什麽是偽隨機數。 什麽是偽隨機數?   1、真正意義上的隨機數在某次產生過程中是按照實驗過程中表現的分布概率隨機產生的,其結果是不可預測的,是不

java-生成任意格式的json數據

mob utf 功能 [] charset logs ejs response 接口 最近研究java的東西。之前靠著自己的摸索,實現了把java對象轉成json格式的數據的功能,返回給前端。當時使用的是 JSONObject.fromObject(object) 方法把j

生成任意範圍內的隨機數

srand((unsigned)time(NULL)); unsigned long long Rand(unsigned long long l, unsigned long long r) { unsigned long long x = (unsigned

java生成4位不重複字元(包含大寫字母、小寫字母、數字)

需要生成4位不重複的字元作為唯一引數,要求只能使用大寫字母、小寫字母和數字的組合。大寫字母26個、小寫字母26個、10個數字共62個字元。不重複排列個數:62*62*62*62=14776336個。 /** * * @author wzp * 2016-3-18

java-生成任意格式的json資料

     private  JSONObject createJSONObject() {               JSONObject result = new JSONOb

java生成任意隨機值,字元,數字,其它的都有你來

主角:Math.random() Math.random()是令系統隨機選取大於等於 0.0 且小於 1.0 的偽隨機 double 值,是Java、js等語言常用程式碼。 我要說的是用java語言,實現任意隨機資料 首先我們知道Math.random(

生成重複隨機數序列(Java

從1到n之間抽取出k個不重複的隨機數,用Math.random()實現的話,可參照下面的程式碼。 int r = (int) (Math.random() * n), 生成下標,據此下標,去到numbers數組裡拿到隨機數。然後將numbers[r]的值設定成

java生成重複隨機數【某個範圍0-10】或者【某個陣列int[1,3,56,14,26,22,17]】

【java】廢話不多說直接貼程式碼: /** * 隨機指定範圍內N個不重複的數 * 最簡單最基本的方法 * @param min 指定範圍最小值 * @param max 指定範圍最大值 * @param n 隨機數個數 */ public st

JAVA生成6個1-8的隨機數,要求無重複

[演算法題:生成不重複的隨機數]生成6個1-8的隨機數,要求無重複。先用陣列儲存隨機數,然後判斷是否重複,如果重複重新生成。 方案一: import java.util.Random; publi

java產生任意範圍內不重複隨機數

n:需要的隨機數的數目 min:下限; max:上限 import java.util.* ; class Tester { public static void main(String args[]) { HashSet<Integer> set =

[Java]不重複隨機數生成簡易演算法

方法一 通過單個數組簡易實現不重複隨機數生成,先上原始碼。 /** * 獲取隨機陣列 * @param 源陣列 * @param size 目標陣列大小 * @return 隨機陣列 */ public static int[] getRandomRe

java生成指定範圍內不重複隨機數(包含邊界值)

生成指定範圍內的隨機數rand.nextInt(100);這行程式碼將生成範圍 0~100 之間的隨機數,有趣的是,取值可能為 0,但不可能為 100。因為隨機生成值區間是 [0, 100)範圍內的整數,實際上就是區間 [0, 99]。因為最大邊界為100,可惜不能等於100

生成固定位數隨機數

偽隨機 span div mat 選擇 均勻分布 and 隨機選擇 col (int)((Math.random()*9+1)*100000000) Math.random() 返回帶正號的 double 值,該值大於等於 0.0 且小於 1.0。返回值是一個偽隨

java生成指定範圍的隨機數

min str rand body clas java test class public 要生成在[min,max]之間的隨機整數, import java.util.Random; public class RandomTest { public stati

Java 生成隨機數

範圍 rate 的區別 用戶 boolean ML src () wid Java中常用的兩種產生隨機數的方法 一、java.lang.Math類中的random()方法; 調用這個Math.random()函數能夠返回帶正號的double值,該值大於等於0.0且小於1

Java實驗--課上提到的隨機數生成原理簡單實現(不利用庫生成隨機數的簡單算法)

9.png 技術分享 當前 span col 分享 args 簡單 返回 對於隨機數的實驗,根據課程上的教程,有如下的公式: 對應的變量參數的說明: 其中對應的Mouduls變量對應的就是公式中a的值,在公式中的含義就是相當於要循環多少個數才重復的一個值。 Mult

JS 生成永不重複的隨機序列號

 序列號由大小寫字母 + 數字組成,直接上程式碼: function getRandomCode(length) { if (length > 0) { var data = ["0", "1", "2", "3", "4", "5", "6", "7",

java生成128,256,512bit隨機數

Java有個庫SecureRandom可以生成安全的隨機數 import java.security.SecureRandom SecureRandom random = new SecureRandom(); byte bytes[] = new byte[16]; // 128 bi

JAVA 生成重複訂單號 優化版本 訂單號格式為yyyymmdd後面自增

@Service("orderNumberDubbboServiceImpl") public class OrderNumberDubbboServiceImpl implements OrderNumberDubbboService { private static Logger