簡體   English   中英

在java中生成一個9位Integer,不重復相同的數字

[英]Generate a 9 digit Integer in java without repeating the same number

我是 java 編程的新手,我正在使用數據庫創建一個簡單的銀行管理系統。 我需要創建一個帳號為 9 位數字的用戶帳戶,該帳號不以 0 開頭。此外,所有帳號必須不同(一個帳號可以有重復數字)。 每次我運行該程序時,它應該給我一個 9 位數字,該數字未存儲在“login_info”數據庫中“account_number”下的“accounts”表中。

程序是這樣運行的,

  • 用戶進入登錄頁面
  • 如果他沒有帳戶,他可以 go 到創建帳戶頁面
  • 創建帳戶頁面有 3 個選項卡,人員信息、銀行帳戶信息和在線帳戶信息
  • 用戶必須填寫個人信息才能獲得go到銀行賬戶信息
  • 當用戶進入銀行賬戶信息時,它會顯示之前填寫的項目(個人信息)和一些額外的項目——銀行賬戶類型和賬號
  • 當用戶轉到銀行帳戶信息選項卡時,必須生成帳號。 用戶不能更改帳號。 (賬號必須是之前沒有存入數據庫的)這是我卡的步驟
  • 選擇賬戶類型后,用戶可以go到在線賬戶信息頁面和select一個唯一的用戶名和密碼
  • 之后,用戶可以點擊創建賬戶按鈕來創建他的銀行賬戶和在線賬戶,或者如果他再考慮的話,他可以退出程序
  • 當用戶點擊創建帳戶按鈕時,將運行查詢並將數據插入 MySQL 表。 這是創建帳戶的地方。

該程序運行良好,但我似乎無法生成唯一的銀行帳號。 其他步驟已經完成。

(這不是針對任何商業產品,只是我從事的一個項目,目的是讓自己熟悉 java 的數據庫處理。)

任何想法如何做到這一點?

謝謝你。

這是您可以采取的一種方法,詳細說明了我在上面發布的評論:

  • 預先計算所有有效帳號——共有 3,265,920 個有效組合
    • 第一個數字有 9 個選擇:1-9,
    • 第 2 位有 9 種選擇:0 可用,因此有 10 位可能的數字 (0-9),除了第 1 位使用了某些東西
    • 第三等8個選擇。
    • 所以: 9*9*8*7*6*5*4*3*2組合
  • 將這大約 300 萬個數字中的每一個填充到數據庫表中
  • 包括一個“狀態”字段來表示以下內容:“未認領”、“待定”、“已認領”
  • 所有帳號都以“無人認領”開頭

在您的 Java 應用程序中,當您想向用戶顯示候選帳號時,您可以使用數據庫將單行從“未認領”更新為“待處理”並返回該帳號 - 因此數據庫將強制執行正確性,即使多個呼叫者同時嘗試設置新帳戶。 類似於:“更新帳戶,其中狀態=未聲明設置狀態=待定限制 1”並返回更新后的行。

從那里:

  • 如果用戶接受帳號,只需將狀態從“待處理”更改為“已申領”
  • 如果他們拒絕,請將其改回“無人認領”

在創建所有初始無人認領的帳戶時,這種方法將允許您預先只做一次數字細節。 它確實有一個潛在的缺點,即您有 300 萬行未使用,但總體而言非常簡單 - 無需擔心進一步的組合,或者生成一個數字然后涉及數據庫以查看該數字是否被聲明(如果號碼正在使用中,則重新生成),或者通過數據庫進行任何類型的掃描以用作號碼選擇過程的輸入,或者人們可能提出的任何其他想法。 只需做好前面的工作。

這就是我會做的時尚:

假設我只能在數據庫中讀寫:

-首先,將數據庫的數字加載到新的 HashSet 中。

- 在那之后,我會從最小的數字開始,到最大的數字。 每次計數后,我會在 HashSet 中檢查該數字是否已經存在(如果是,繼續計數)。

- 找到一個號碼后,我會保護最后一個找到的號碼,所以你從最后一個位置開始計數,而不是從下一次開始計數。

(如果您希望數字是絕對隨機的,您也可以只滾動新數字而不是計數。)

如果您可以更改數據庫上的某些內容,我建議您在數字上設置自動增量選項。

如果您希望數字是隨機的,請創建一個從 0 到 899 999 999 的數字,然后添加 100 000 000(所以第一個永遠不會是 0)。 如果數字存儲在 Arraylist 中(在本例中稱為 nums),則以下代碼應該會有所幫助:

        int num;
        Do{
            num = (int)(Math.random()*800000000)+100000000;
        }while (nums.contains(num));
        nums.add(num);

例如:

final var digits = IntStream.range(1, 10).boxed().collect(Collectors.toList());
Collections.shuffle(digits);
final var result = digits.stream().reduce(0, (x, y) -> 10 * x + y);
System.out.println(result);

我正在使用數據庫來創建一個簡單的銀行管理系統。 我需要使用不以 0 開頭的 9 位帳號創建用戶帳戶。此外,所有帳號必須不同。 每次我運行該程序時,它都會給我一個 9 位數字,該數字未存儲在“login_info”數據庫中“account_number”下的“accounts”表中。

這實際上是一個出乎意料的復雜問題。 最佳答案取決於您未提及的其他因素:

  • 帳號是否必須是唯一的“每次程序運行”或“每次在同一運行期間請求一個帳號(但不一定從運行到運行)”?
  • 這是一個單線程環境(即,有多少同時執行的線程可能試圖同時創建帳號)?
  • 賬號是否有認同感 它是否需要能夠始終唯一地標識特定帳戶(或者有時,可能是從表單創建帳戶時,當帳戶不需要具有身份時?
  • 什么管理身份? 你的程序系統? 您用於存儲信息的數據庫?

如果第一個項目符號答案是“每次程序運行”,那么您需要考慮如何在運行之間保持帳號種子(用於生成下一個可用帳號的數量或數量)(否則,當 JVM 退出時,種子會被銷毀)。

如果第二個項目是“多線程”,那么你需要考慮如何防止相同的帳號被無意中提供給同時請求一個的線程。

其余的項目符號處理身份。 帳號通常用於識別系統的特定帳戶(但不一定)。 因此,您必須考慮身份何時需要對系統可用。 您還必須考慮哪個系統負責管理身份。 如果在創建賬戶實體時就需要標識,則需要在 Java 實例化賬戶時獲取。 如果在將帳戶實體持久化到數據庫之前不需要它,那么數據庫系統可能會創建身份。

混合解決方案是在實例化后立即持久化帳戶,然后再次讀取它以獲取帳號(以增加數據庫流量為代價)。 如果帳戶根本不需要持久化(例如,它已被取消),則可能需要邏輯來刪除數據庫記錄。

根據對這些問題的回答,以及其他重要因素(例如可用性、可擴展性、冗余、安全性等),原始問題的完整解決方案可能會變得任意復雜。

但是如果我們假設帳號只需要在 Java 系統的同一運行期間是唯一的,並且帳戶訪問只是單線程的,那么解決方案可能會變得非常簡單:

public static class AccountNumberManager {
    private static long accountNumberSeed = getStartupSeedValue();

    private AccountNumberManager() { }

    public long getNextAccountNumber() {
        return ++accountNumberSeed;
    }

    private static long getStartupSeedValue() {
        return 100000000L;
    }
}

一些簡短的說明:

  • 用於帳號管理的static類使帳號種子值線程的初始化是安全的。 初始值初始化發生在類在加載過程中被類加載器鎖定時,因此是線程安全的(類及其靜態字段只能初始化一次)。 這是靜態持有者類的初始化方法 如果系統曾經演變成並發環境,這將很方便。

  • 當然,該解決方案假定在初始化帳戶實體時需要帳號。 無論如何,我認為這是一個很好的做法。 我的偏見是,盡可能不使用數據庫系統來創建系統范圍的標識符(僅用於持久化它們)。

  • 使用帳號作為數據庫主鍵不是最佳實踐。 這是一個相當廣泛的觀點,而不是普遍的觀點。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM