如果 hashString 是纳米时间,Hashing.crc32 是否会生成一个唯一的字符串?

Does Hashing.crc32 generate a unique string if the hashString is a nanotime?

我正在开发一个 url 缩短器,我必须在 java 中生成一个像这样的唯一字符串“3d0d1fb8”,以便缩短url 像这样:shrt.it/3d0d1fb8

我正在使用此代码:

String nanotime = String.valueOf(System.nanoTime());    
String uniqueId = Hashing.crc32().hashString(nanotime, StandardCharsets.UTF_8).toString();

这个“uniqueId”是一个真正独特的字符串吗?

不,任何 32 位散列在大约 60K 个值后都会得到一个副本。任何两个字符串都可以具有相同的哈希值。

如果您想查看随机 32 位值的重复速度,您可以运行这会在几秒钟内产生数千个结果。

public static void main(String[] args) {
    Random rand = new Random();
    int range = 1 << 30;
    BitSet bs = new BitSet(range);
    while (true) {
        int value = rand.nextInt();
        if (value >= 0 && value < range)
            if (bs.get(value))
                System.out.println("Duplicate " + value);
            else
                bs.set(value);
    }
}

获得唯一 ID 的更简单方法是使用时间戳,例如 System.currentTimeMillis() 转换为 base 36,但您只能确保它对于单个 JVM 是唯一的。

例如

import java.util.concurrent.atomic.AtomicLong;

// unique for a JVM, and ok on restart provided less than 1000 ids/sec
public enum UniqueTimestamp {
    INSTANCE;
    final AtomicLong time = new AtomicLong();

    public long uniqueTime() {
        long now = System.currentTimeMillis();
        long value = time.get();
        long next = Math.max(now, value) + 1;
        if (time.compareAndSet(value, next))
            return next;
        return time.incrementAndGet();
    }

    public String uniqueId() {
        return Long.toString(uniqueTime(), Character.MAX_RADIX /*36*/);
    }
}

哪里

    for (int i = 0; i < 5; i++)
        System.out.println(UniqueTimestamp.INSTANCE.uniqueId());

打印

jae4gmp2
jae4gmp3
jae4gmp4
jae4gmp5
jae4gmp6

What do you do if you have multiple JVMs?

您可以在分配给 JVM 的每个 ID 的开头添加一个或多个唯一字符。例如一个添加 a,另一个添加 b