您可以生成 10 位 base-36 数字。为了使它们不可预测,您可以使用与 36^10 相对质数的任何值跳过它们,而不是一个接一个。
例如:
public class Unique {
private static final long SKIP = 1656158440062971L;
private static final long MOD = 3656158440062976L;
private static final long BASE = 36L;
public static class ExhaustedException extends RuntimeException {
public ExhaustedException() { super("No more codes"); }
}
private long currentValue = 0L;
public static void main(String[] args) {
int max = Integer.parseInt(args[0]);
Unique generator = new Unique();
for (int i = 0; i < max; i++) {
System.out.println(generator.nextCode());
}
}
public synchronized String nextCode() {
currentValue = (currentValue + SKIP) % MOD;
if (currentValue == 0L) {
throw new ExhaustedException();
}
return codeFromLong(currentValue);
}
private String codeFromLong(long value) {
StringBuilder code = new StringBuilder();
for (int i = 0; i < 10; i++) {
int digit = (int) (value % BASE);
code.insert(0, charFromDigit(digit));
value /= BASE;
}
return code.toString();
}
private char charFromDigit(int digit) {
if (digit < 10) return (char) ('0' + digit);
return (char) ('A' + (digit - 10));
}
}
这将以明显随机的顺序生成 10 个字符的字母数字代码。它将在 3,656,158,440,062,976(3.6 万亿)个代码之后重复。为了防止重复,在它生成一个 0 然后重复之前它会抛出一个ExhaustedException。保证每个代码只访问一次,因为 1,656,158,440,062,971 是总循环长度的质数。
我通过将第一个数字更改为 1 并调整最后一个数字来生成此值。这个数到底是什么并不重要,它不需要是素数,但它不能与 36^10 共享任何公因数(必须是互质数),它应该很大但不接近 36 ^10 以便每次转动曲柄时大部分或所有数字都会改变。
这是一个独立的程序,但您可能希望将当前值放入数据库中,甚至可能将此代码放在存储过程后面,在这种情况下,您可能希望它返回一些不同的标记值以指示序列已用尽。我已经制作了生成下一个代码synchronized的方法;您需要以一种或另一种方式确保没有两个调用者收到相同的代码。
注意:这意味着这可能会成为您应用的瓶颈。
我还会在它周围加上一个包装器,并检查咒语的停止列表。您不想给客户一个包含四个字母或其他冒犯性词的代码。如果代码包含作为子字符串的坏词,只需将其丢弃并生成下一个代码。