java 生成 NanoId 自定义生成位数和 ID 的取值范围

2,362 阅读1分钟

Java 生成 NanoId 随机数

1. pom.xml 文件引入依赖

<dependency>
   <groupId>com.aventrix.jnanoid</groupId>
   <artifactId>jnanoid</artifactId>
   <version>2.0.0</version>
</dependency>

2.新建 NanoIdUtils.java 工具类

package com.example.demo.EasyExcelDemo.Utils;

import java.security.SecureRandom;
import java.util.Random;

public final class NanoIdUtils {
    public static final SecureRandom DEFAULT_NUMBER_GENERATOR = new SecureRandom();
    // 随机生成的字符内容
    public static final char[] DEFAULT_ALPHABET = "_-0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ".toCharArray();
    // 随机生成 ID 的位数
    public static final int DEFAULT_SIZE = 10;

    private NanoIdUtils() {
    }

    public static String randomNanoId() {
        return randomNanoId(DEFAULT_NUMBER_GENERATOR, DEFAULT_ALPHABET, DEFAULT_SIZE);
    }

    public static String randomNanoId(Random random, char[] alphabet, int size) {
        if (random == null) {
            throw new IllegalArgumentException("random cannot be null.");
        } else if (alphabet == null) {
            throw new IllegalArgumentException("alphabet cannot be null.");
        } else if (alphabet.length != 0 && alphabet.length < 256) {
            if (size <= 0) {
                throw new IllegalArgumentException("size must be greater than zero.");
            } else {
                int mask = (2 << (int)Math.floor(Math.log((double)(alphabet.length - 1)) / Math.log(2.0D))) - 1;
                int step = (int)Math.ceil(1.6D * (double)mask * (double)size / (double)alphabet.length);
                StringBuilder idBuilder = new StringBuilder();

                while(true) {
                    byte[] bytes = new byte[step];
                    random.nextBytes(bytes);

                    for(int i = 0; i < step; ++i) {
                        int alphabetIndex = bytes[i] & mask;
                        if (alphabetIndex < alphabet.length) {
                            idBuilder.append(alphabet[alphabetIndex]);
                            if (idBuilder.length() == size) {
                                return idBuilder.toString();
                            }
                        }
                    }
                }
            }
        } else {
            throw new IllegalArgumentException("alphabet must contain between 1 and 255 symbols.");
        }
    }
}

3. 方法引用,这里和 UUID 做了一下比较

public static void main(String[] args) {
    for (int i = 0; i < 10; i++) {
        System.out.println(NanoIdUtils.randomNanoId());
    }
}

4. 结果示例

51mc61ZcfM
0LOYhTiZ31
lMQnNxKytu
RXAJ0JKep8
9Op0sxphP1
OcdryFXCvp
JtMcMHjLiX
KUJ1kuqjR7
NJvTQNaHB4
GiyQ6TbVbL