簡體   English   中英

唯一的字符串ID生成器算法

[英]unique string ID gererator algorithm

我正在閱讀一個開源項目aventrix / jnanoid ,我聽不懂mask和代碼中的step

public static String randomNanoId(final Random random, final char[] alphabet, final int size) {

    if (random == null) {
        throw new IllegalArgumentException("random cannot be null.");
    }

    if (alphabet == null) {
        throw new IllegalArgumentException("alphabet cannot be null.");
    }

    if (alphabet.length == 0 || alphabet.length >= 256) {
        throw new IllegalArgumentException("alphabet must contain between 1 and 255 symbols.");
    }

    if (size <= 0) {
        throw new IllegalArgumentException("size must be greater than zero.");
    }

    final int mask = (2 << (int) Math.floor(Math.log(alphabet.length - 1) / Math.log(2))) - 1;
    final int step = (int) Math.ceil(1.6 * mask * size / alphabet.length);

    final StringBuilder idBuilder = new StringBuilder();

    while (true) {

        final byte[] bytes = new byte[step];
        random.nextBytes(bytes);

        for (int i = 0; i < step; i++) {

            final int alphabetIndex = bytes[i] & mask;

            if (alphabetIndex < alphabet.length) {
                idBuilder.append(alphabet[alphabetIndex]);
                if (idBuilder.length() == size) {
                    return idBuilder.toString();
                }
            }

        }

    }

}

在循環中,我們嘗試在每次循環迭代中選擇字母表的隨機成員(字母)。 請注意,這在給定的循環迭代中可能會失敗,因為我們可以獲得的索引大於字母表的長度。 我們通過創建隨機字節數組來選擇字母。 然后,我們只使用每個隨機字節的足夠位,以確保我們可以選擇字母表中的任何字母。 因此,如果我們的字母有兩個字符,則一個位就足夠了,因為它可以具有值0或1。如果我們的字母有9個字符,則需要四個位,因為三個位只能表示8個值(0-7)。 這就是面具。 我們掩蓋了隨機字節的后四位,並將它們用作字母表的索引。 因此,如果我們的隨機字節為11000110,那么在我的示例中,我們將低四位(0110)用於9個字符的字母。 0110是十進制的6,因此我們在字符數組的索引6處選擇字母。 現在您可以看到它如何失敗。 如果我們的隨機字節是01001101,那么我們將屏蔽1011(即十進制的13),它超出了9個字母的結尾。 如前所述,使用該算法設置掩碼的代碼可確保它足夠長以覆蓋整個字母,但是不能防止它太長。

我不得不說,步驟對我而言似乎有些武斷。 如果您查看循環步驟,則是我們試圖獲取長度大小隨機字符串的字節數。 我們已經看到,單個循環迭代可能無法選擇字母,因此步幅需要大於大小。 多長時間取決於掩碼相對於我們的字母長度的多少,因此乘以mask / alphabet.length是有意義的。 盡管如此,我們仍然不能選擇足夠多的隨機字母,因此我們將其提高了1.6左右。 當然,我們仍然會失敗(我們所有的隨機字節都可能指向超出字母表末尾的字母),這就是為什么在其中擁有while(true)的原因:如果失敗,我們將再次嘗試。

暫無
暫無

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

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