android,如何在应用端生成较短版本的uuid(13个字符)

android,如何在应用端生成较短版本的uuid(13个字符),android,uuid,Android,Uuid,android应用程序需要生成包含13个字符的uuid。但这可能会增加冲突的可能性。 使用这个函数时,想法是添加uuid的最高/最低有效位,然后从长字符串中获取字符串。然后从结果中找出13字节长度的部分。测试运行似乎没有在单机(+100000个UUID)上看到冲突。 但不确定机器之间发生冲突的可能性 是否有更好的方法生成13个字符uuid和合理的低分类率 val random = Random() fun generateUUID() { val uuid: UUID = UUID.ra

android应用程序需要生成包含13个字符的uuid。但这可能会增加冲突的可能性。 使用这个函数时,想法是添加uuid的最高/最低有效位,然后从长字符串中获取字符串。然后从结果中找出13字节长度的部分。测试运行似乎没有在单机(+100000个UUID)上看到冲突。 但不确定机器之间发生冲突的可能性

是否有更好的方法生成13个字符uuid和合理的低分类率

val random = Random()
fun generateUUID() {
    val uuid: UUID = UUID.randomUUID()
    val theLong = if (random.nextBoolean()) {
            uuid.mostSignificantBits + uuid.leastSignificantBits
        } else {
            uuid.leastSignificantBits + uuid.mostSignificantBits
        }
    return java.lang.Long.toString(theLong, Character.MAX_RADIX)
}

它将不再是严格意义上的UUID;UUID描述了一个非常具体的数据结构。使用适当UUID的低位通常是个坏主意;这些都不是独一无二的。单机测试将是不确定的

编辑:现在我想起来了,问题中的“char”到底是什么?十进制数字?十六进制数字?一个字节?ASCII字符?Unicode字符?如果是后者,您可以在那里填充完整的适当UUID。只需将其表示为二进制,而不是十六进制字符串。UUID的长度为128位。Unicode码点是20位,因此其中13位将覆盖260位,这就足够了

Java
char
数据类型实际上略小于16位。如果“13个字符”是指长度为13的Java字符串(或13个字符的数组),那么仍然可以在其中填充UUID,并使用一些技巧来避免保留UTF-16代理项对值


综上所述,对于全局唯一ID生成,它们通常使用当前时间、随机数和某种特定于设备的标识符的组合,散列在一起。这就是工作原理。根据大小限制的确切性质(这在问题中是模糊的),建议使用不同的哈希算法


编辑:关于使用整个Unicode范围。第一件事:您确实意识到“du3d2t5fdaib4”和“8efc9756-70ff-4a9f-bf45-4c693bde61a4”都是十六进制字符串,对吗?它们只使用16个字符,0-9和a-f?第二个破折号可以安全地省略,它们只是为了可读性。同时,一个Java
char
可以有63488个可能的值中的一个-除了子范围0xD800..0xDFFF之外,从0到0xFFFF的任何代码点都可以。包含所有这些疯狂字符的字符串将不好看,甚至无法打印;它可能看起来像“芦№Π║ثЯ"; 有些字符可能不会在Android中显示,因为它们不在系统字体中,但它将是唯一的

是否要求唯一字符串能够很好地显示


如果没有,让我们看看。UUID是两个64位Java
long
s。它是Java中的签名数据类型;如果没有签名的话会容易些,但是没有这样的事。但是,我们可以将两个long视为4整数,并确保整数为正

现在我们有4个正整数可以填充到13个字符中。我们也不想弄乱跨越可变边界的算法,所以让我们将每个整数转换成一个3个字符的块,没有重叠。这会浪费一些空间,但哦,好吧,我们还有一些空间可以利用。int的长度为4字节,而3个Java字符的长度为6字节

在组成字符时,我们希望避免D800和DFFF之间的区域。此外,我们希望避免从0到1F的代码点-这些是设计上无法打印的控制字符。另外,让我们避免使用字符0x20-这是空格。现在,我不知道字符串将如何使用是否在不允许转义的文本格式中使用,因此是否应避免使用某些其他字符以简化下游操作

一个连续的字符范围更容易使用,所以让我们完全放弃0xD800以上的范围。这就给我们留下了0xD7DF不同的代码点,从0x21开始。其中三个足以覆盖32位整数。将整数转换为字符三元组的规则很简单:将整数除以0xD7DF两次,取余数,将余数添加到基码点(即0x21)。这个算法是“将整数转换为以N为基数的字符串”的普通算法,它知道整数不能超过三位数

综合考虑,以下是Java:

public static String uuidToWeirdString(UUID uuid)
{
    //Description of our alphabet: from 021 to 0xD7FF
    final int ALPHA_SIZE = 0xD7DF, ALPHA_BASE = 0x21;

    //Convert the UUID to a pair of signed, potentially negative longs
    long low = uuid.getLeastSignificantBits(),
        high = uuid.getMostSignificantBits();

    //Convert to positive 32-bit ints, represented as signed longs
    long []parts = {
        (high >> 32) & 0xffffffff,
        high & 0xffffffff,
        (low >> 32) & 0xffffffff,
        low & 0xffffffff
    };

    //Convert ints to char triples
    int nPart, pos = 0;
    char []c = new char[12];
    for(nPart=0;nPart<4;nPart++)
    {
        long part = parts[nPart];
        c[pos++] = (char)(ALPHA_BASE + part / (ALPHA_SIZE*ALPHA_SIZE));
        c[pos++] = (char)(ALPHA_BASE + (part / ALPHA_SIZE ) % ALPHA_SIZE);
        c[pos++] = (char)(ALPHA_BASE + part % ALPHA_SIZE);
    }
    return new String(c);
}
公共静态字符串UUIDTowerString(UUID UUID)
{
//我们的字母表描述:从021到0xD7FF
最终整数ALPHA_大小=0xD7DF,ALPHA_基数=0x21;
//将UUID转换为一对有符号的、可能为负的长字符串
long low=uuid.getLeastSignificantBits(),
高=uuid.getMostSignificantBits();
//转换为正32位整数,表示为带符号的长整数
长[]部分={
(高>>32)和0xffffffff,
高&0xffffffff,
(低>>32)和0xffffffff,
低&0xffffffff
};
//将整数转换为字符三元组
int nPart,位置=0;
char[]c=新字符[12];

对于(nPart=0;nPart它将不再是严格意义上的UUID;UUID描述了一个非常具体的数据结构。使用适当UUID的低位通常是一个坏主意;它们从来都不是唯一的。单机测试将是不确定的

编辑:现在我想起来了,“char”到底是什么在问题中,十进制数字?十六进制数字?字节?ASCII字符?Unicode字符?如果是后者,你可以在那里填充一个完整的UUID。只需将其表示为二进制,而不是十六进制字符串。UUID是128位长。Unicode码点是20位,其中13位将覆盖260位,这很好h

Java
char
数据类型实际上略小于16位。如果“13个字符”是指长度为13的Java字符串(或13个字符的数组),您仍然可以在其中填充UUID,并使用一些技巧来避免保留UTF-16代理项对值


A