我想要一个有效的实用程序来生成唯一的字节序列。UUID是一个很好的候选,但UUID. randomuuid (). tostring()会生成44e128a5-ac7a-4c9a-be4c-224b6bf81b20这样的东西,这很好,但我更喜欢无虚线字符串。

我正在寻找一种有效的方法来生成随机字符串,只从字母数字字符(没有破折号或任何其他特殊符号)。


当前回答

我刚刚复制了UUID toString()方法,并更新了它以删除“-”。它会比其他解决方案更快更直接

public String generateUUIDString(UUID uuid) {
    return (digits(uuid.getMostSignificantBits() >> 32, 8) +
            digits(uuid.getMostSignificantBits() >> 16, 4) +
            digits(uuid.getMostSignificantBits(), 4) +
            digits(uuid.getLeastSignificantBits() >> 48, 4) +
            digits(uuid.getLeastSignificantBits(), 12));
}

/** Returns val represented by the specified number of hex digits. */
private String digits(long val, int digits) {
    long hi = 1L << (digits * 4);
    return Long.toHexString(hi | (val & (hi - 1))).substring(1);
}

用法:

generateUUIDString(UUID.randomUUID())

使用反射的另一个实现

public String generateString(UUID uuid) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {

    if (uuid == null) {
        return "";
    }

    Method digits = UUID.class.getDeclaredMethod("digits", long.class, int.class);
    digits.setAccessible(true);

    return ( (String) digits.invoke(uuid, uuid.getMostSignificantBits() >> 32, 8) +
            digits.invoke(uuid, uuid.getMostSignificantBits() >> 16, 4) +
            digits.invoke(uuid, uuid.getMostSignificantBits(), 4) +
            digits.invoke(uuid, uuid.getLeastSignificantBits() >> 48, 4) +
            digits.invoke(uuid, uuid.getLeastSignificantBits(), 12));

}

其他回答

最后我基于UUID.java实现编写了自己的东西。注意,我没有生成UUID,而是以我能想到的最有效的方式生成一个随机的32字节十六进制字符串。

实现

import java.security.SecureRandom;
import java.util.UUID;

public class RandomUtil {
    // Maxim: Copied from UUID implementation :)
    private static volatile SecureRandom numberGenerator = null;
    private static final long MSB = 0x8000000000000000L;

    public static String unique() {
        SecureRandom ng = numberGenerator;
        if (ng == null) {
            numberGenerator = ng = new SecureRandom();
        }

        return Long.toHexString(MSB | ng.nextLong()) + Long.toHexString(MSB | ng.nextLong());
    }       
}

使用

RandomUtil.unique()

测试

我测试了一些输入,以确保它是有效的:

public static void main(String[] args) {
    System.out.println(UUID.randomUUID().toString());
    System.out.println(RandomUtil.unique());

    System.out.println();
    System.out.println(Long.toHexString(0x8000000000000000L |21));
    System.out.println(Long.toBinaryString(0x8000000000000000L |21));
    System.out.println(Long.toHexString(Long.MAX_VALUE + 1));
}

我刚刚复制了UUID toString()方法,并更新了它以删除“-”。它会比其他解决方案更快更直接

public String generateUUIDString(UUID uuid) {
    return (digits(uuid.getMostSignificantBits() >> 32, 8) +
            digits(uuid.getMostSignificantBits() >> 16, 4) +
            digits(uuid.getMostSignificantBits(), 4) +
            digits(uuid.getLeastSignificantBits() >> 48, 4) +
            digits(uuid.getLeastSignificantBits(), 12));
}

/** Returns val represented by the specified number of hex digits. */
private String digits(long val, int digits) {
    long hi = 1L << (digits * 4);
    return Long.toHexString(hi | (val & (hi - 1))).substring(1);
}

用法:

generateUUIDString(UUID.randomUUID())

使用反射的另一个实现

public String generateString(UUID uuid) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {

    if (uuid == null) {
        return "";
    }

    Method digits = UUID.class.getDeclaredMethod("digits", long.class, int.class);
    digits.setAccessible(true);

    return ( (String) digits.invoke(uuid, uuid.getMostSignificantBits() >> 32, 8) +
            digits.invoke(uuid, uuid.getMostSignificantBits() >> 16, 4) +
            digits.invoke(uuid, uuid.getMostSignificantBits(), 4) +
            digits.invoke(uuid, uuid.getLeastSignificantBits() >> 48, 4) +
            digits.invoke(uuid, uuid.getLeastSignificantBits(), 12));

}

我使用JUG (Java UUID Generator)来生成唯一的ID。 它在jvm中是唯一的。很好用。以下是代码供您参考:

private static final SecureRandom secureRandom = new SecureRandom();
private static final UUIDGenerator generator = UUIDGenerator.getInstance();

public synchronized static String generateUniqueId() {
  UUID uuid = generator.generateRandomBasedUUID(secureRandom);

  return uuid.toString().replaceAll("-", "").toUpperCase();
}

你可以从https://github.com/cowtowncoder/java-uuid-generator下载这个库

我很惊讶看到这么多字符串取代UUID的想法。这个怎么样:

UUID temp = UUID.randomUUID();
String uuidString = Long.toHexString(temp.getMostSignificantBits())
     + Long.toHexString(temp.getLeastSignificantBits());

这是最快的方法,因为整个UUID的toString()已经更加昂贵,更不用说正则表达式,它必须被解析和执行或替换为空字符串。

一个简单的解决方案是

UUID.randomUUID().toString().replace("-", "")

(像现有的解决方案一样,只是它避免了String#replaceAll调用。这里不需要正则表达式替换,因此string# replace感觉更自然,尽管从技术上讲它仍然是用正则表达式实现的。由于生成UUID的开销比替换UUID的开销更大,因此在运行时不应该有显著差异。)

对于大多数场景来说,使用UUID类可能已经足够快了,不过我希望一些不需要后期处理的专门手写变体会更快。总之,整个计算的瓶颈通常是随机数生成器。对于UUID类,它使用securerrandom。

使用哪个随机数生成器也取决于应用程序。如果对安全性敏感,一般建议使用SecureRandom。否则,ThreadLocalRandom是一种替代方案(比securerrandom或旧的Random快,但不加密安全)。