如何在Java中创建用户友好的唯一ID、UUID或其他唯一标识符

如何在Java中创建用户友好的唯一ID、UUID或其他唯一标识符,java,random,uuid,Java,Random,Uuid,我通常使用UUID类来生成唯一的ID。如果这些ID仅由技术系统使用,则可以正常工作,它们不关心它们的长度: System.out.println(UUID.randomUUID().toString()); > 67849f28-c0af-46c7-8421-94f0642e5d4d 有没有一种很好的方法来创建比UUID短一点的用户友好的唯一ID(比如tinyurl中的ID)?用例:您希望通过邮件将ID发送给您的客户,这些客户反过来访问您的站点,并在表单中输入该号码,如凭证ID 我假设

我通常使用UUID类来生成唯一的ID。如果这些ID仅由技术系统使用,则可以正常工作,它们不关心它们的长度:

System.out.println(UUID.randomUUID().toString());

> 67849f28-c0af-46c7-8421-94f0642e5d4d
有没有一种很好的方法来创建比UUID短一点的用户友好的唯一ID(比如tinyurl中的ID)?用例:您希望通过邮件将ID发送给您的客户,这些客户反过来访问您的站点,并在表单中输入该号码,如凭证ID

我假设UUID在UUID的128位范围内的整个范围内都是平等生成的。那么,仅使用较低的64位是否明智呢

System.out.println(UUID.randomUUID().getLeastSignificantBits());
欢迎任何反馈。

仅适用于您:):

private final static char[]idchars=“abcdefghijklmnopqrstuvxyzabcdefghijklmnopqrstuvxyz012456789”。tocharray();
私有静态字符串createId(int len){
char[]id=新字符[len];
Random r=新的Random(System.currentTimeMillis());
对于(int i=0;i
我假设uuid是生成的 在整个过程中都是一样的 UUID的128位范围

首先,根据UUID类型(1、2、3或4),您的假设可能不正确。发件人:

存在着不同的语言变体 这些是全局标识符。方法 这个类的 Leach Salz变体,尽管 构造函数允许创建任何 UUID的变体(如下所述)

变体2(Leach Salz)的布局 UUID如下所示:最 重要的长代码包括 以下未签名字段:

最不重要的长代码包括 以下未签名字段:

变量字段包含一个值 它标识了 乌伊德。上面描述的位布局 仅对具有 变量值2,表示 Leach-Salz变体

version字段包含一个 描述此UUID的类型。那里 有四种不同的基本类型 UUID:基于时间的DCE安全性, 基于名称,随机生成 UUIDs。这些类型有一个版本 值分别为1、2、3和4

最好的方法是生成一个随机字符串,代码如下():

公共类随机字符串{
公共静态字符串随机字符串(int-lo,int-hi){
int n=兰特(低,高);
字节b[]=新字节[n];
对于(int i=0;i
如果您非常担心冲突或其他问题,我建议您
base64
对UUID进行编码,这样可以减少UUID的大小


故事的寓意:不要依赖UUID的各个部分,因为它们是整体设计的。如果确实需要依赖UUID的各个部分,请确保熟悉特定的UUID类型和实现。

以下是生成用户友好ID的另一种方法:


(但您应该使用坏字过滤器)

任何UUID/Guid都只有16字节的数据。这16个字节可以使用BASE64(或BASE64url)轻松编码,然后去掉字符串末尾的所有“=”字符


这提供了一个很好的短字符串,它仍然保存与UUID/Guid相同的数据。换句话说,如果有必要,可以从该数据重新创建UUID/Guid。

这个如何?实际上,这段代码最多返回13个字符(数字和小写字母)


下面是一种生成URL友好的22个字符UUID的方法

public static String generateShortUuid() {
        UUID uuid = UUID.randomUUID();

        long lsb = uuid.getLeastSignificantBits();
        long msb = uuid.getMostSignificantBits();

        byte[] uuidBytes = ByteBuffer.allocate(16).putLong(msb).putLong(lsb).array();

        // Strip down the '==' at the end and make it url friendly   
        return Base64.encode(uuidBytes)
                    .substring(0, 22)
                    .replace("/", "_")
                    .replace("+", "-");
    }
对于您的用例,最好跟踪已注册用户的运行计数,并为每个值生成如下所示的字符串标记:

public static String longToReverseBase62(long value /* must be positive! */) {

        final char[] LETTERS = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ".toCharArray();

        StringBuilder result = new StringBuilder(9);
        do {
            result.append(LETTERS[(int)(value % 62)]);
            value /= 62l;
        }
        while (value != 0);

        return result.toString();
    }

出于安全原因,如果您将这些值设置为非顺序的,那就更好了,因此每次用户注册时,您都可以将该值增加1024(比如说,为2^64/2^10=2^54用户生成UUID会很好,这肯定比您需要的要多:)

在撰写本文时,这个问题的标题是:

如何在Java中创建用户友好的唯一ID、UUID或其他唯一标识符

生成用户友好的ID是一个主观问题。如果您有一个唯一的值,有许多方法可以将其格式化为“用户友好”的值,它们都可以归结为将唯一值与“用户友好”ID一一映射-如果输入值是唯一的,“用户友好”ID也同样是唯一的

此外,通常不可能创建一个同样唯一的随机值,至少如果每个随机值是独立于任何其他值生成的。此外,如果要生成唯一标识符(来自my),您应该问自己很多问题:

  • 应用程序能否在所需范围内轻松检查标识符的唯一性(例如,检查具有该标识符的文件或数据库记录是否已存在)
  • 应用程序能否承受为不同资源生成相同标识符的风险
  • 标识符必须是难以猜测的,仅仅是“随机的”,还是两者都不是
  • 你知道吗
    0xC000000000000000 variant 
    0x3FFF000000000000 clock_seq 
    0x0000FFFFFFFFFFFF node  
    
    public class RandomString {
    
              public static String randomstring(int lo, int hi){
                      int n = rand(lo, hi);
                      byte b[] = new byte[n];
                      for (int i = 0; i < n; i++)
                              b[i] = (byte)rand('a', 'z');
                      return new String(b, 0);
              }
    
              private static int rand(int lo, int hi){
                          java.util.Random rn = new java.util.Random();
                      int n = hi - lo + 1;
                      int i = rn.nextInt(n);
                      if (i < 0)
                              i = -i;
                      return lo + i;
              }
    
              public static String randomstring(){
                      return randomstring(5, 25);
              }
    
            /**
             * @param args
             */
            public static void main(String[] args) {
                    System.out.println(randomstring());
    
            }
    
    }
    
    import java.nio.ByteBuffer;
    import java.util.UUID;
    
    /**
     * Generate short UUID (13 characters)
     * 
     * @return short UUID
     */
    public static String shortUUID() {
      UUID uuid = UUID.randomUUID();
      long l = ByteBuffer.wrap(uuid.toString().getBytes()).getLong();
      return Long.toString(l, Character.MAX_RADIX);
    }
    
    public static String generateShortUuid() {
            UUID uuid = UUID.randomUUID();
    
            long lsb = uuid.getLeastSignificantBits();
            long msb = uuid.getMostSignificantBits();
    
            byte[] uuidBytes = ByteBuffer.allocate(16).putLong(msb).putLong(lsb).array();
    
            // Strip down the '==' at the end and make it url friendly   
            return Base64.encode(uuidBytes)
                        .substring(0, 22)
                        .replace("/", "_")
                        .replace("+", "-");
        }
    
    public static String longToReverseBase62(long value /* must be positive! */) {
    
            final char[] LETTERS = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ".toCharArray();
    
            StringBuilder result = new StringBuilder(9);
            do {
                result.append(LETTERS[(int)(value % 62)]);
                value /= 62l;
            }
            while (value != 0);
    
            return result.toString();
        }