在 JAVA 中生成 UUID 字符串的有效方法(UUID.randomUUID().toString() 没有破折号)

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/3804591/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-14 05:15:06  来源:igfitidea点击:

Efficient method to generate UUID String in JAVA (UUID.randomUUID().toString() without the dashes)

javarandomuuid

提问by Maxim Veksler

I would like an efficient utility to generate unique sequences of bytes. UUID is a good candidate but UUID.randomUUID().toString()generates stuff like 44e128a5-ac7a-4c9a-be4c-224b6bf81b20which is good, but I would prefer dash-less string.

我想要一个有效的实用程序来生成唯一的字节序列。UUID 是一个很好的候选者,但UUID.randomUUID().toString()生成的东西44e128a5-ac7a-4c9a-be4c-224b6bf81b20很好,但我更喜欢无破折号的字符串。

I'm looking for an efficient way to generate a random strings, only from alphanumeric characters (no dashes or any other special symbols).

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

采纳答案by Maxim Veksler

Ended up writing something of my own based on UUID.java implementation. Note that I'm not generating a UUID, instead just a random 32 bytes hex string in the most efficient way I could think of.

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

Implementation

执行

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());
    }       
}

Usage

用法

RandomUtil.unique()

Tests

测试

Some of the inputs I've tested to make sure it's working:

我测试过的一些输入以确保它正常工作:

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));
}

回答by Steve McLeod

This does it:

这样做:

public static void main(String[] args) {
    final String uuid = UUID.randomUUID().toString().replace("-", "");
    System.out.println("uuid = " + uuid);
}

回答by Donz

Dashes don't need to be removed from HTTP request as you can see in URL of this thread. But if you want to prepare well-formed URL without dependency on data you should use URLEncoder.encode( String data, String encoding ) instead of changing standard form of you data. For UUID string representation dashes is normal.

正如您在此线程的 URL 中看到的那样,不需要从 HTTP 请求中删除破折号。但是,如果您想准备不依赖数据的格式良好的 URL,您应该使用 URLEncoder.encode( String data, String encoding ) 而不是更改数据的标准形式。对于 UUID 字符串表示,破折号是正常的。

回答by Sheng Chien

I used JUG (Java UUID Generator) to generate unique ID. It is unique across JVMs. Pretty good to use. Here is the code for your reference:

我使用 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();
}

You could download the library from: https://github.com/cowtowncoder/java-uuid-generator

您可以从以下位置下载该库:https: //github.com/cowtowncoder/java-uuid-generator

回答by stikkos

I use org.apache.commons.codec.binary.Base64 to convert a UUID into a url-safe unique string that is 22 characters in length and has the same uniqueness as UUID.

我使用 org.apache.commons.codec.binary.Base64 将 UUID 转换为长度为 22 个字符且与 UUID 具有相同唯一性的 url-safe 唯一字符串。

I posted my code on Storing UUID as base64 String

我在将 UUID 存储为 base64 字符串上发布了我的代码

回答by Stephan

I am amazed to see so many string replace ideas of UUID. How about this:

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

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

This is the fasted way of doing it since the whole toString() of UUID is already more expensive not to mention the regular expression which has to be parsed and executed or the replacing with empty string.

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

回答by Philipp Cla?en

A simple solution is

一个简单的解决方案是

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

(Like the existing solutions, only that it avoids the String#replaceAllcall. Regular expression replacement is not required here, so String#replacefeels more natural, though technically it still is implemented with regular expressions. Given that the generation of the UUID is more costly than the replacement, there should not be a significant difference in runtime.)

(和现有方案一样,只是避免了String#replaceAll的调用。这里不需要替换正则表达式,所以String#replace感觉更自然,不过技术上还是用正则表达式实现的。鉴于UUID的生成是比更换成本更高,运行时应该没有显着差异。)

Using the UUID class is probably fast enough for most scenarios, though I would expect that some specialized hand-written variant, which does not need the postprocessing, to be faster. Anyway, the bottleneck of the overall computation will normally be the random number generator. In case of the UUID class, it uses SecureRandom.

对于大多数场景,使用 UUID 类可能足够快,但我希望一些不需要后处理的专门手写变体更快。无论如何,整体计算的瓶颈通常是随机数生成器。对于 UUID 类,它使用SecureRandom

Which random number generator to use is also a trade-off that depends on the application. If it is security-sensitive, SecureRandom is, in general, the recommendation. Otherwise, ThreadLocalRandomis an alternative (faster than SecureRandom or the old Random, but not cryptographically secure).

使用哪种随机数生成器也是一种权衡,取决于应用程序。如果它是安全敏感的,SecureRandom 通常是推荐的。否则,ThreadLocalRandom是另一种选择(比 SecureRandom 或旧的Random快,但不是加密安全的)。

回答by Ravi Desai

I have just copied UUID toString() method and just updated it to remove "-" from it. It will be much more faster and straight forward than any other solution

我刚刚复制了 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);
}

Usage:

用法:

generateUUIDString(UUID.randomUUID())

generateUUIDString(UUID.randomUUID())

Another implementation using reflection

使用反射的另一种实现

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));

}