Java中的顺序Guid

时间:2010-02-04 16:59:25

标签: java guid sequential

考虑到我在Microsoft.NET框架上发布的关于顺序guid性能的帖子(参见What are the performance improvement of Sequential Guid over standard Guid?)确实有人在Windows中实现了相同算法的正确,可靠,快速且运行良好的Java实现的DLL?

此致 马西莫

5 个答案:

答案 0 :(得分:5)

请参阅此文章:http://www.informit.com/articles/article.aspx?p=25862&seqNum=7(与第7页相关联)。

它包含作者所称的“COMB”Guids的算法;我在下面重现他的代码(SQL):

SET @aGuid = CAST(CAST(NEWID() AS BINARY(10)) 
+ CAST(GETDATE() AS BINARY(6)) AS UNIQUEIDENTIFIER)

将此转换为Java或您想要的语言是微不足道的。明显的基本原则是使日期成为Guid的一个组成部分。整篇文章读得很好,因为他对各种方法的表现做了很好的分析。

答案 1 :(得分:3)

对于顺序UUID,您正在寻找版本1 UUID。 Java UUID Generator项目似乎工作得很好并且很容易使用:

Generators.timeBasedGenerator().generate().toString()

答案 2 :(得分:2)

此页面链接到Java中的几个版本1(顺序)UUID实现: http://johannburkard.de/blog/programming/java/Java-UUID-generators-compared.html

答案 3 :(得分:0)

由Jimmy Nilsson在本文http://www.informit.com/articles/article.aspx?p=25862中构思的,生成COMB UUID的实用程序类。随时使用和共享。

package your.package.name;

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

/**
 * Utility class that creates COMB UUIDs.
 * 
 * The COMB UUIDs combine the creation time and random bytes.
 * 
 * The PREFIX or SUFFIX has 6 bytes and corresponds to the milliseconds since
 * 1970-01-01T00:00:00Z (Unix epoch).
 * 
 * For RFC-4122 compliance, it uses the version number 4.
 * 
 * Read: The Cost of GUIDs as Primary Keys
 * http://www.informit.com/articles/article.aspx?p=25862
 * 
 */
public abstract class CombUuidCreator {

    private static final int RANDOM_VERSION = 4;

    /**
     * Returns a prefix COMB UUID.
     * 
     * It uses a thread local {@link SecureRandom}.
     * 
     * @return a random-based UUID
     */
    public static UUID getPrefixComb() {
        return getPrefixComb(SecureRandomLazyHolder.THREAD_LOCAL_RANDOM.get());
    }

    /**
     * Returns a prefix COMB UUID.
     * 
     * It uses any instance of {@link Random}.
     * 
     * @return a random-based UUID
     */
    public static UUID getPrefixComb(Random random) {
        return getCombGuid(random, /* prefix = */true);
    }

    /**
     * Returns a suffix COMB UUID.
     * 
     * It uses a thread local {@link SecureRandom}.
     * 
     * @return a random-based UUID
     */
    public static UUID getSuffixComb() {
        return getSuffixComb(SecureRandomLazyHolder.THREAD_LOCAL_RANDOM.get());
    }

    /**
     * Returns a suffix COMB UUID.
     * 
     * It uses any instance of {@link Random}.
     * 
     * @return a random-based UUID
     */
    public static UUID getSuffixComb(Random random) {
        return getCombGuid(random, /* prefix = */false);
    }

    /**
     * Returns prefix or suffix COMB UUID.
     * 
     * It uses any instance of {@link Random}.
     * 
     * @return a random-based UUID
     */
    private static UUID getCombGuid(Random random, boolean prefix) {

        long msb = 0;
        long lsb = 0;

        // (3) set bits randomly
        final byte[] bytes = new byte[16];
        random.nextBytes(bytes);
        final long rand0 = (bytes[8] << 8) | (bytes[9] & 0xff);
        final long rand1 = toNumber(bytes, 0, 8);

        // Insert the prefix in the MSB
        final long timestamp = System.currentTimeMillis();
        if (prefix) {
            msb = (rand0 & 0x000000000000ffffL) | ((timestamp & 0x0000ffffffffffffL) << 16);
            lsb = rand1;
        } else {
            msb = rand1;
            lsb = (rand0 << 48) | (timestamp & 0x0000ffffffffffffL);
        }

        // Apply version and variant bits (required for RFC-4122 compliance)
        msb = (msb & 0xffffffffffff0fffL) | (RANDOM_VERSION & 0x0f) << 12; // apply version bits
        lsb = (lsb & 0x3fffffffffffffffL) | 0x8000000000000000L; // apply variant bits

        // Return the UUID
        return new UUID(msb, lsb);
    }

    private static long toNumber(final byte[] bytes, final int start, final int length) {
        long result = 0;
        for (int i = start; i < length; i++) {
            result = (result << 8) | (bytes[i] & 0xff);
        }
        return result;
    }

    // Holds thread local secure random
    private static class SecureRandomLazyHolder {
        static final ThreadLocal<Random> THREAD_LOCAL_RANDOM = ThreadLocal.withInitial(SecureRandom::new);
    }

    /**
     * For tests!
     */
    public static void main(String[] args) {

        Random random = new Random();

        System.out.println("// Prefix COMB using thread local `java.security.SecureRandom` (DEFAULT)");
        System.out.println("CombUuidCreator.getPrefixComb()");
        System.out.println();
        for (int i = 0; i < 5; i++) {
            System.out.println(" " + CombUuidCreator.getPrefixComb());
        }
        System.out.println("|----prefix---|----------------------|");

        System.out.println();
        System.out.println("// Prefix COMB using `java.util.Random` (FASTER)");
        System.out.println("CombUuidCreator.getPrefixComb(new Random())");
        System.out.println();
        for (int i = 0; i < 5; i++) {
            System.out.println(" " + CombUuidCreator.getPrefixComb(random));
        }
        System.out.println("|----prefix---|----------------------|");

        System.out.println();
        System.out.println("// Suffix COMB using thread local `java.security.SecureRandom` (DEFAULT)");
        System.out.println("CombUuidCreator.getSuffixComb()");
        System.out.println();
        for (int i = 0; i < 5; i++) {
            System.out.println(" " + CombUuidCreator.getSuffixComb());
        }
        System.out.println("|-----------------------|---suffix---|");

        System.out.println();
        System.out.println("// Suffix COMB using `java.util.Random` (FASTER)");
        System.out.println("CombUuidCreator.getSuffixComb(new Random())");
        System.out.println();
        for (int i = 0; i < 5; i++) {
            System.out.println(" " + CombUuidCreator.getSuffixComb(random));
        }
        System.out.println("|-----------------------|---suffix---|");
    }
}

这是输出:

// Prefix COMB using thread local `java.security.SecureRandom` (DEFAULT)
CombUuidCreator.getPrefixComb()

 0173861f-4445-459b-87d2-39a970520fff
 0173861f-4445-465d-a216-7b13d86c83a1
 0173861f-4445-4c67-b75e-3845c2911420
|----prefix---|----------------------|

// Prefix COMB using `java.util.Random` (FASTER)
CombUuidCreator.getPrefixComb(new Random())

 0173861f-4445-44f6-bfa4-e272c9c369aa
 0173861f-4445-446e-baf2-6db6ab808094
 0173861f-4445-40e8-a452-184dcf9736fd
|----prefix---|----------------------|

// Suffix COMB using thread local `java.security.SecureRandom` (DEFAULT)
CombUuidCreator.getSuffixComb()

 726b6717-001a-4317-9a9b-0173861f4446
 dfdce2d2-7517-4a3f-9f3d-0173861f4446
 a7fd6236-8065-4395-b49a-0173861f4446
|-----------------------|---suffix---|

// Suffix COMB using `java.util.Random` (FASTER)
CombUuidCreator.getSuffixComb(new Random())

 41a6a4cd-eb4c-410f-8eb2-0173861f4446
 7c0a315e-54de-476a-a2a8-0173861f4446
 4e9ddf9e-ac07-4cf3-bf3f-0173861f4446
|-----------------------|---suffix---|

您还可以使用uuid-creator库。请参阅以下示例:

// Create a prefix COMB UUID
UUID uuid = UuidCreator.getPrefixComb();

// Create a suffix COMB UUID
UUID uuid = UuidCreator.getSuffixComb();

项目页面:https://github.com/f4b6a3/uuid-creator

答案 4 :(得分:-3)

我用它为我的DTO生成UUID(通用唯一ID),它作为瞬态集合的代理键。不知道它是否是同一个东西,但它可能指向你正确的方向。

import java.util.UUID;
...
    private String uuid=null;
...
    protected String getUuid() {
        synchronized (this) {
          if (null ==uuid) {
            uuid = UUID.randomUUID().toString();
          }
          return uuid;
        }
      }