GitHub - f4b6a3/ulid-creator: A Java library for generating Universally Unique Lexicographically Sortable Identifiers (ULID) (original) (raw)

This is a Java implementation of Universally Unique Lexicographically Sortable Identifier.

In summary:

This project contains a micro benchmark and a good amount of unit tests.

The jar file can be downloaded directly from maven.org.

Read the Javadocs.

Usage

Create a ULID:

Ulid ulid = UlidCreator.getUlid();

Create a Monotonic ULID:

Ulid ulid = UlidCreator.getMonotonicUlid();

Dependency

Add these lines to your pom.xml.

com.github.f4b6a3 ulid-creator 5.2.4

See more options in maven.org.

Modularity

Module and bundle names are the same as the root package name.

ULID

ULID is a 128-bit identifier. The first 48 bits represent the number of milliseconds since Unix Epoch, 1970-01-01. The remaining 80 bits are generated by a secure random number generator. Its canonical string representation is 26 characters long.

// Generate a ULID Ulid ulid = UlidCreator.getUlid();

Structure of a series of ULIDs:

01EX8Y21KBH49ZZCA7KSKH6X1C
01EX8Y21KBJTFK0JV5J20QPQNR
01EX8Y21KBG2CS1V6WQCTVM7K6
01EX8Y21KB8HPZNBP3PTW7HVEY
01EX8Y21KB3HZV38VAPTPAG1TY
01EX8Y21KB9FTEJHPAGAKYG9Z8
01EX8Y21KBQGKGH2SVPQAYEFFC
01EX8Y21KBY17J9WR9KQR8SE7H
01EX8Y21KCVHYSJGVK4HBXDMR9 < millisecond changed
01EX8Y21KC668W3PEDEAGDHMVG
01EX8Y21KC53D2S5ADQ2EST327
01EX8Y21KCPQ3TENMTY1S7HV56
01EX8Y21KC3755QF9STQEV05EB
01EX8Y21KC5ZSHK908GMDK69WE
01EX8Y21KCSGJS8S1FVS06B3SX
01EX8Y21KC6ZBWQ0JBV337R1CN
         ^ look

|---------|--------------|
    time      random

Monotonic ULID

Monotonic ULID is a variant of ULID. The random component is incremented by 1 whenever the current millisecond equals the previous millisecond. Its main advantage is speed.

// Generate a Monotonic ULID Ulid ulid = UlidCreator.getMonotonicUlid();

Structure of a series of Monotonic ULIDs:

01EX8Y7M8MDVX3M3EQG69EEMJW
01EX8Y7M8MDVX3M3EQG69EEMJX
01EX8Y7M8MDVX3M3EQG69EEMJY
01EX8Y7M8MDVX3M3EQG69EEMJZ
01EX8Y7M8MDVX3M3EQG69EEMK0
01EX8Y7M8MDVX3M3EQG69EEMK1
01EX8Y7M8MDVX3M3EQG69EEMK2
01EX8Y7M8MDVX3M3EQG69EEMK3
01EX8Y7M8N1G30CYF2PJR23J2J < millisecond changed
01EX8Y7M8N1G30CYF2PJR23J2K
01EX8Y7M8N1G30CYF2PJR23J2M
01EX8Y7M8N1G30CYF2PJR23J2N
01EX8Y7M8N1G30CYF2PJR23J2P
01EX8Y7M8N1G30CYF2PJR23J2Q
01EX8Y7M8N1G30CYF2PJR23J2R
01EX8Y7M8N1G30CYF2PJR23J2S
         ^ look          ^ look

|---------|--------------|
    time      random

Hash ULID

Hash ULID is a "non-standard" variant of ULID. It always returns the same ULID for a specific pair of arguments. It has the same basic structure as a ULID, except that the random component is replaced with the first 10 bytes of an SHA-256 hash.

// Generate a Hash ULID of a string long time = file.getCreatedAt(); String name = file.getFileName(); Ulid ulid = UlidCreator.getHashUlid(time, name);

// Generate a Hash ULID of a byte array long time = file.getCreatedAt(); byte[] bytes = file.getFileBinary(); Ulid ulid = UlidCreator.getHashUlid(time, bytes);

Structure of Hash ULIDs:

01GZ8AR53SE5XCA1MN1PGCSDJ0

|---------|--------------|

    time        hash

More Examples

Create a quick ULID:


Create a ULID from a canonical string (26 chars):

Ulid ulid = Ulid.from("0123456789ABCDEFGHJKMNPQRS");


Convert a ULID into a canonical string in lower case:

String string = ulid.toLowerCase(); // 0123456789abcdefghjkmnpqrs


Convert a ULID into a UUID:

UUID uuid = ulid.toUuid(); // 0110c853-1d09-52d8-d73e-1194e95b5f19


Convert a ULID into a RFC-4122 UUID v4:

UUID uuid = ulid.toRfc4122().toUuid(); // 0110c853-1d09-42d8-973e-1194e95b5f19 // ^ UUID v4


Get the creation instant of a ULID:

Instant instant = ulid.getInstant(); // 2007-02-16T02:13:14.633Z


// static method Instant instant = Ulid.getInstant("0123456789ABCDEFGHJKMNPQRS"); // 2007-02-16T02:13:14.633Z


Get only the time component substring:

String ulidTimePart = ulid.toString() .substring(0, Ulid.TIME_CHARS); // 0123456789


Get only the random component substring:

String ulidRandPart = ulid.toString() .substring(Ulid.TIME_CHARS, Ulid.RANDOM_CHARS); // ABCDEFGHJKMNPQRS


Insert a string between the time and random components efficiently (avoiding concatenation) (#29):

String ulidExpanded = new StringBuilder(ulid.toString()) .insert(Ulid.TIME_CHARS, "-INSERTED-") .toString(); // 0123456789-INSERTED-ABCDEFGHJKMNPQRS


A key generator that makes substitution easy if necessary:

package com.example;

import com.github.f4b6a3.ulid.UlidCreator;

public class KeyGenerator { public static String next() { return UlidCreator.getUlid().toString(); } }

// use the generator String key = KeyGenerator.next();


A UlidFactory with java.util.Random:

// use a java.util.Random instance for fast generation UlidFactory factory = UlidFactory.newInstance(new Random());

// use the factory Ulid ulid = factory.create();


A UlidFactory with RandomGenerator (JDK 17+):

// use a random function that returns a long value RandomGenerator random = RandomGenerator.getDefault(); UlidFactory factory = UlidFactory.newInstance(() -> random.nextLong());

// use the factory Ulid ulid = factory.create();


Benchmark

This section shows benchmarks comparing UlidCreator to UUID.randomUUID().

--------------------------------------------------------------------------------
THROUGHPUT (operations/msec)            Mode  Cnt      Score      Error   Units
--------------------------------------------------------------------------------
UUID_randomUUID                        thrpt    5   1787,601 ±  489,482  ops/ms ( 1.0)
UUID_randomUUID_toString               thrpt    5   1598,467 ±   93,067  ops/ms
-  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -
Ulid_fast                              thrpt    5 100521,737 ±27132,748  ops/ms (56.2)
Ulid_fast_toString                     thrpt    5  50529,743 ± 8970,574  ops/ms
-  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -
UlidCreator_getUlid                    thrpt    5   2443,810 ±  379,149  ops/ms ( 1.3)
UlidCreator_getUlid_toString           thrpt    5   2200,047 ±  539,767  ops/ms
-  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -
UlidCreator_getMonotonicUlid           thrpt    5   9845,810 ± 1239,148  ops/ms ( 5.5)
UlidCreator_getMonotonicUlid_toString  thrpt    5   5748,568 ±  549,121  ops/ms
-  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -
UlidCreator_getHashUlid                thrpt    5   6651,239 ± 2541,774  ops/ms
UlidCreator_getHashUlidString          thrpt    5   6043,582 ± 1879,042  ops/ms
--------------------------------------------------------------------------------
Total time: 00:03:22
--------------------------------------------------------------------------------

System: CPU i7-8565U, 16G RAM, Ubuntu 22.04, JVM 11, rng-tools installed.

To execute the benchmark, run ./benchmark/run.sh.

Other identifier generators

Check out the other ID generators from the same family:

License

This library is Open Source software released under the MIT license.