ããã¯ããªã«ãããããŠæžãããã®ïŒ
Javaã§UUIDã䜿ãããšæã£ãããjava.util.UUID#randomUUID#toString
ã§ããŒãžã§ã³4ã®UUIDã䜿ã£ãŠãããšæããŸãã
ã§ããUUIDã£ãŠããŒãžã§ã³4以å€ã«ãçš®é¡ããããŸããããããšããããšã§ãJavaã§ããŒãžã§ã³4以å€ã®UUIDãæ±ããã©ã€ãã©ãªãŒã
調ã¹ãŠã¿ãŸããã
UUIDã®ããŒãžã§ã³
ãããããUUIDã«ã€ããŠå°ãèŠãŠãããŸããããUUIDã®RFCã¯ãã¡ãã§ãã
RFC 4122: A UUID URN Namespace
UUIDã¯128ãããã®æ°åã§ãäžæã®èå¥åãšãªããã®ã§ãã以äžã®ãããªæãã§ããã
jshell> java.util.UUID.randomUUID().toString() $1 ==> "a3240b70-d32d-4551-86d2-3bf5fc07649f"
UUIDã®åœ¢åŒã¯ä»¥äžãšãªã£ãŠããŸãã
The formal definition of the UUID string representation is provided by the following ABNF [7]: UUID = time-low "-" time-mid "-" time-high-and-version "-" clock-seq-and-reserved clock-seq-low "-" node time-low = 4hexOctet time-mid = 2hexOctet time-high-and-version = 2hexOctet clock-seq-and-reserved = hexOctet clock-seq-low = hexOctet node = 6hexOctet hexOctet = hexDigit hexDigit hexDigit = "0" / "1" / "2" / "3" / "4" / "5" / "6" / "7" / "8" / "9" / "a" / "b" / "c" / "d" / "e" / "f" / "A" / "B" / "C" / "D" / "E" / "F"
time-high-and-versionãã£ãŒã«ãã«ã¯ããŒãžã§ã³ãå«ãŸããŠããŠã-
åºåãã®3ã€ç®ã®æåã®æåã¯ããŒãžã§ã³çªå·ã«ãªããŸãã
The version number is in the most significant 4 bits of the time
stamp (bits 4 through 7 of the time_hi_and_version field).
ããšãã°ãå
ã»ã©ã®äŸã ãš4551
ã®éšåã®4
ãã¿ã€ã4ã§ããããšã衚ããŠããŸãã
jshell> java.util.UUID.randomUUID().toString() $1 ==> "a3240b70-d32d-4551-86d2-3bf5fc07649f"
RFC 4122ã§ã¯ã5ã€ã®ããŒãžã§ã³ã®UUIDãå®ããããŠããŸãã
- ããŒãžã§ã³1
- ã¿ã€ã ã¹ã¿ã³ããšMACã¢ãã¬ã¹ãå ã«ãããã®
- ããŒãžã§ã³2
- DCEã»ãã¥ãªãã£UUIDãšåŒã°ããããŒãžã§ã³1ã®äžéšãPOSIXã®ãŠãŒã¶ãŒIDãã°ã«ãŒãIDã§å·®ãæ¿ãããã®
- ããŒãžã§ã³3
- ããåå空éããæœåºãããååãšãããã·ã¥é¢æ°ãšããŠMD5ãå©çšãããã®
- ããŒãžã§ã³4
- ä¹±æ°ããçæãããã®
- ããŒãžã§ã³5
- ããŒãžã§ã³3ã®ããã·ã¥é¢æ°ãSHA1ã«ãããã®
ãããŠããã«ããã©ããæ®µéã®ãã®ãææ¡ãããŠããŠããã®äžã«ã¯ããŒãžã§ã³6ã7ã8ãå«ãŸããŠããŸãã
A Universally Unique IDentifier (UUID) URN Namespace
GitHub - uuid6/uuid6-ietf-draft: Next Generation UUID Formats
ãã®äžã§ã¯ãUUIDã¯äžæã§ããç¹æ§ã掻ãããŠããŒã¿ããŒã¹ã®ããŒãšããŠãã䜿ããããã®ã®ããªãŒãã€ã³ã¯ãªã¡ã³ããªãã®ãšããŠã¯
䜿ããªããšããããšãèšãããŠããŸãã
One area UUIDs have gained popularity is as database keys. This stems from the increasingly distributed nature of modern applications. In such cases, "auto increment" schemes often used by databases do not work well, as the effort required to coordinate unique numeric identifiers across a network can easily become a burden. The fact that UUIDs can be used to create unique, reasonably short values in distributed systems without requiring synchronization makes them a good alternative, but UUID versions 1-5 lack certain other desirable characteristics
ãããŠããœãŒãå¯èœãªèå¥åãå®ããããšãåæ©ã«ãªã£ãŠããŸãã
Due to the aforementioned issue, many widely distributed database applications and large application vendors have sought to solve the problem of creating a better time-based, sortable unique identifier for use as a database key. This has lead to numerous implementations over the past 10+ years solving the same problem in slightly different ways.
ããããã®ããŒãžã§ã³ã®ç¹æ§ã¯ã以äžã§ãã
- ããŒãžã§ã³6
- ããŒãžã§ã³1ãæ¹åããã¿ã€ã ã¹ã¿ã³ãã®æ å ±ããœãŒãå¯èœãªåœ¢ã«èŠçŽãããã®
- ããŒãžã§ã³7
- Unixãšããã¯ã¿ã€ã ã¹ã¿ã³ãããæŽŸçãããã£ãŒã«ãæã¡ãããŒãžã§ã³1ã6ãããšã³ããããŒãæ¹åãããã®
- ããŒãžã§ã³8
- å®éšçãŸãã¯ãã³ããŒåºæã®ãŠãŒã¹ã±ãŒã¹åãã®ãã®
ããŒãžã§ã³8ã¯ãã¡ãã£ãšæ±ããéããŸããã
ãŸã ãã©ããæ®µéã§ãããããŒãžã§ã³7ããã䜿ãããããšã«ãªãããã§ããã
ãªãããœãŒãå¯èœãªäžæãªIDãªããULIDãšãããã®ããããŸãã
JavaでULIDを使いたい(Sulky ULIDを使う) - CLOVER🍀
Javaã§ã®UUIDã®éžæè¢
ããã§Javaã§ã®UUIDã®éžæè¢ãæ¢ããŠã¿ããšã以äžã®ãããªæãã§ããã
- UUID (Java SE 17 & JDK 17)
- ããŒãžã§ã³4
- Commons Id - UUID Documentation
- Apache Commons Id
- ããŒãžã§ã³1ã3ã4ã5
- UUID – About
- ããŒãžã§ã³1
- https://johannburkard.de/software/uuid/
- ããŒãžã§ã³1
- GitHub - f4b6a3/uuid-creator: A Java library for generating Universally Unique Identifiers (UUID).
- ããŒãžã§ã³1ã2ã3ã4ã5ã6ã7
- GitHub - cowtowncoder/java-uuid-generator: Java Uuid Generator (JUG) is a library for generating all (3) types of UUIDs on Java. See (http://github.com/tlaukkan/mono-uuid-generator) for C#-based sister project!
- ããŒãžã§ã³1ã4ã5ã6ã7
- äœè ã¯Jacksonã®éçºè
æŽæ°ç¶æ ãªã©ãèŠãŠãå®éã«äœ¿ãããšæããšä»¥äžãããããçµã蟌ãã®ããªãšæããŸãã
- UUID (Java SE 17 & JDK 17)
- GitHub - f4b6a3/uuid-creator: A Java library for generating Universally Unique Identifiers (UUID).
- GitHub - cowtowncoder/java-uuid-generator: Java Uuid Generator (JUG) is a library for generating all (3) types of UUIDs on Java. See (http://github.com/tlaukkan/mono-uuid-generator) for C#-based sister project!
ä»åã¯ãJava Uuid GeneratorïŒJUGïŒã詊ããŠã¿ãŸãã
ç°å¢
ä»åã®ç°å¢ã¯ããã¡ãã
$ java --version openjdk 17.0.8 2023-07-18 OpenJDK Runtime Environment (build 17.0.8+7-Ubuntu-122.04) OpenJDK 64-Bit Server VM (build 17.0.8+7-Ubuntu-122.04, mixed mode, sharing) $ mvn --version Apache Maven 3.9.4 (dfbb324ad4a7c8fb0bf182e6d91b0ae20e3d2dd9) Maven home: $HOME/.sdkman/candidates/maven/current Java version: 17.0.8, vendor: Private Build, runtime: /usr/lib/jvm/java-17-openjdk-amd64 Default locale: ja_JP, platform encoding: UTF-8 OS name: "linux", version: "5.15.0-78-generic", arch: "amd64", family: "unix"
Java Uuid GeneratorïŒJUGïŒã䜿ã
Java Uuid GeneratorïŒJUGïŒã®GitHubãªããžããªãŒã¯ããã¡ãã
ããã¥ã¡ã³ãã¯README.md
ã®ã¿ã§ãWikiããã¯Javadocããã©ãããšãã§ããŸãã
Home · cowtowncoder/java-uuid-generator Wiki · GitHub
äœ¿ãæ¹ã¯ããã¡ãã
Java Uuid Generator (JUG) / Usage
äŸåé¢ä¿ã远å ããŠ
Java Uuid Generator (JUG) / Usage / Maven Dependency
ãã¡ãã«åŸã£ãŠUUIDãçæããã©ã€ãã©ãªãŒãšããŠäœ¿ããŸãã
Java Uuid Generator (JUG) / Usage / Using JUG as Library
ãŸããåäœã§CLIãšããŠã䜿ããããã§ãã
Java Uuid Generator (JUG) / Usage / Using JUG as CLI
ä»åã¯ãã©ã€ãã©ãªãŒãšããŠäœ¿ã£ãŠã¿ãŸãã
æºå
MavenäŸåé¢ä¿çã¯ãã¡ãã
<properties> <maven.compiler.source>17</maven.compiler.source> <maven.compiler.target>17</maven.compiler.target> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> </properties> <dependencies> <dependency> <groupId>com.fasterxml.uuid</groupId> <artifactId>java-uuid-generator</artifactId> <version>4.2.0</version> </dependency> <dependency> <groupId>org.junit.jupiter</groupId> <artifactId>junit-jupiter</artifactId> <version>5.10.0</version> <scope>test</scope> </dependency> <dependency> <groupId>org.assertj</groupId> <artifactId>assertj-core</artifactId> <version>3.24.2</version> <scope>test</scope> </dependency> </dependencies> <build> <plugins> <plugin> <artifactId>maven-surefire-plugin</artifactId> <version>3.1.2</version> </plugin> </plugins> </build>
Java Uuid GeneratorïŒJUGïŒã«å¿ èŠãªäŸåé¢ä¿ã¯ããã¡ãã§ããã
<dependency> <groupId>com.fasterxml.uuid</groupId> <artifactId>java-uuid-generator</artifactId> <version>4.2.0</version> </dependency>
確èªã¯ãã¹ãã³ãŒãã§ããã®ã§ãJUnit 5ãšAssertJãå ¥ããŠããŸãã
䜿ã£ãŠã¿ã
ã§ã¯ãJava Uuid GeneratorïŒJUGïŒã䜿ã£ãŠã¿ãŸãã
ãã¹ãã³ãŒãã®é圢ã¯ãã¡ãã
src/test/java/org/littlewings/uuid/JugGettingStartedTest.java
package org.littlewings.uuid; import com.fasterxml.uuid.Generators; import com.fasterxml.uuid.impl.*; import org.junit.jupiter.api.Test; import java.util.UUID; import static org.assertj.core.api.Assertions.assertThat; class JugGettingStartedTest { // ããã«ããã¹ããæžãïŒ }
以äžã®README.md
ã«ãæžãããŠããããã«ãèµ·ç¹ã¯com.fasterxml.uuid.Generators
ã«ãªããŸãã
Java Uuid Generator (JUG) / Usage / Using JUG as LibraryGenerating UUIDs
ãããªæãã§ããã
@Test void simple() { UUID uuidV1 = Generators.timeBasedGenerator().generate(); System.out.printf("UUID v1 = %s%n", uuidV1.toString()); assertThat(uuidV1.toString()).containsPattern("^[^-]+-[^-]+-1[^-]+-[^-]+-[^-]+$"); UUID uuidV4 = Generators.randomBasedGenerator().generate(); System.out.printf("UUID v4 = %s%n", uuidV4.toString()); assertThat(uuidV4.toString()).containsPattern("^[^-]+-[^-]+-4[^-]+-[^-]+-[^-]+$"); UUID uuidV5 = Generators.nameBasedGenerator().generate("source name"); System.out.printf("UUID v5 = %s%n", uuidV5.toString()); assertThat(uuidV5.toString()).containsPattern("^[^-]+-[^-]+-5[^-]+-[^-]+-[^-]+$"); UUID uuidV6 = Generators.timeBasedReorderedGenerator().generate(); System.out.printf("UUID v6 = %s%n", uuidV6.toString()); assertThat(uuidV6.toString()).containsPattern("^[^-]+-[^-]+-6[^-]+-[^-]+-[^-]+$"); UUID uuidV7 = Generators.timeBasedEpochGenerator().generate(); System.out.printf("UUID v7 = %s%n", uuidV7.toString()); assertThat(uuidV7.toString()).containsPattern("^[^-]+-[^-]+-7[^-]+-[^-]+-[^-]+$"); }
Generators
ããç®çã«ãã£ãcom.fasterxml.uuid.UUIDGenerator
ã¯ã©ã¹ã®ãµãã¯ã©ã¹ã®ã€ã³ã¹ã¿ã³ã¹ãçæããgenerate
ã¡ãœããã
䜿ãããšã§UUID
ãåŸãããŸãã
System.out.printf
ããŠããçµæã¯ãã¡ãã§ãã
UUID v1 = acaffd7b-3465-11ee-a8c8-d57e5908feb4 UUID v4 = da265cbd-2c53-46fa-a65c-bd2c53a6fa22 UUID v5 = 6c7475b2-9251-5490-82ca-c2d1a2af1b98 UUID v6 = 1ee3465a-cb8f-6e2c-a8c8-1d53d7fe1737 UUID v7 = 0189cb40-f3ea-74f8-b863-7f05ac9cd0c8
æ£èŠè¡šçŸã§ç¢ºèªããŠããŸããã-
åºåãã®3ã€ç®ã®å
é ã¯ããŒãžã§ã³çªå·ã«ãªã£ãŠããŸããã
ã¡ãã£ãšé©ããã®ã¯ãçæãããUUIDã¯java.util.UUID
ã®ã€ã³ã¹ã¿ã³ã¹ã ãšããããšã§ããç¬èªã®ã¯ã©ã¹ã«ãªã£ãŠããã®ããªïŒãšæã£ãŠ
ããã®ã§ãããããã§ã¯ãããŸããã§ããã
åcom.fasterxml.uuid.UUIDGenerator
ã¯ã©ã¹ã®ã€ã³ã¹ã¿ã³ã¹ã¯ããããªæãã«ä¿æããŠäœ¿ããŸããããšãã§ããŸãã
@Test void generator() { TimeBasedGenerator timeBasedGenerator = Generators.timeBasedGenerator(); assertThat(timeBasedGenerator.generate().toString()).containsPattern("^[^-]+-[^-]+-1[^-]+-[^-]+-[^-]+$"); assertThat(timeBasedGenerator.generate().toString()).containsPattern("^[^-]+-[^-]+-1[^-]+-[^-]+-[^-]+$"); RandomBasedGenerator randomBasedGenerator = Generators.randomBasedGenerator(); assertThat(randomBasedGenerator.generate().toString()).containsPattern("^[^-]+-[^-]+-4[^-]+-[^-]+-[^-]+$"); assertThat(randomBasedGenerator.generate().toString()).containsPattern("^[^-]+-[^-]+-4[^-]+-[^-]+-[^-]+$"); NameBasedGenerator nameBasedGenerator = Generators.nameBasedGenerator(); assertThat(nameBasedGenerator.generate("source name1").toString()).containsPattern("^[^-]+-[^-]+-5[^-]+-[^-]+-[^-]+$"); assertThat(nameBasedGenerator.generate("source name2").toString()).containsPattern("^[^-]+-[^-]+-5[^-]+-[^-]+-[^-]+$"); TimeBasedReorderedGenerator timeBasedReorderedGenerator = Generators.timeBasedReorderedGenerator(); assertThat(timeBasedReorderedGenerator.generate().toString()).containsPattern("^[^-]+-[^-]+-6[^-]+-[^-]+-[^-]+$"); assertThat(timeBasedReorderedGenerator.generate().toString()).containsPattern("^[^-]+-[^-]+-6[^-]+-[^-]+-[^-]+$"); TimeBasedEpochGenerator timeBasedEpochGenerator = Generators.timeBasedEpochGenerator(); assertThat(timeBasedEpochGenerator.generate().toString().toString()).containsPattern("^[^-]+-[^-]+-7[^-]+-[^-]+-[^-]+$"); assertThat(timeBasedEpochGenerator.generate().toString().toString()).containsPattern("^[^-]+-[^-]+-7[^-]+-[^-]+-[^-]+$"); }
README.md
ã«ãããšãåGeneratorã¯ã¹ã¬ããã»ãŒãã ããã§ãã
Generators are fully thread-safe, so a single instance may be shared among multiple threads.
com.fasterxml.uuid.Generators
ã®JavadocãèŠãŠãããšããã§ãããã
Generators (Java UUID Generator 4.2.0 API)
äžæãªIDãçæãããããšã確èªãã
æåŸã«ã倧éã®UUIDçæïŒãã«ãã¹ã¬ããã§äžæãªIDãäœæã§ããŠããããç°¡åã«ç¢ºèªãããã¹ããæžããŠã¿ãŸãã
src/test/java/org/littlewings/uuid/CreatedUUIDsTest.java
package org.littlewings.uuid; import com.fasterxml.uuid.Generators; import com.fasterxml.uuid.impl.*; import org.junit.jupiter.api.Test; import java.util.Set; import java.util.UUID; import java.util.concurrent.*; import java.util.function.IntFunction; import java.util.stream.Collectors; import java.util.stream.IntStream; import static org.assertj.core.api.Assertions.assertThat; class CreatedUUIDsTest { void uniqueness(IntFunction<UUID> generator, int times) { ExecutorService es = Executors.newFixedThreadPool(10); try { Set<Future<String>> futures = IntStream .rangeClosed(1, times) .mapToObj(i -> es.submit(() -> generator.apply(i).toString())) .collect(Collectors.toSet()); Set<String> ids = futures .stream() .map(f -> { try { return f.get(); } catch (ExecutionException | InterruptedException e) { throw new RuntimeException(e); } }) .collect(Collectors.toSet()); assertThat(ids).hasSize(times); } finally { es.shutdown(); try { es.awaitTermination(10L, TimeUnit.SECONDS); } catch (InterruptedException e) { // ignore } } } @Test void v1() { TimeBasedGenerator timeBasedGenerator = Generators.timeBasedGenerator(); uniqueness(count -> timeBasedGenerator.generate(), 10_000_000); } @Test void v4() { RandomBasedGenerator randomBasedGenerator = Generators.randomBasedGenerator(); uniqueness(count -> randomBasedGenerator.generate(), 10_000_000); } @Test void v5() { NameBasedGenerator nameBasedGenerator = Generators.nameBasedGenerator(); uniqueness(count -> nameBasedGenerator.generate("source name" + count), 10_000_000); } @Test void v6() { TimeBasedReorderedGenerator timeBasedReorderedGenerator = Generators.timeBasedReorderedGenerator(); uniqueness(count -> timeBasedReorderedGenerator.generate(), 10_000_000); } @Test void v7() { TimeBasedEpochGenerator timeBasedEpochGenerator = Generators.timeBasedEpochGenerator(); uniqueness(count -> timeBasedEpochGenerator.generate(), 10_000_000); } }
確ãã«ããã«ãã¹ã¬ããç°å¢äžã§ãåé¡ã«ã¯ãªããªãããã§ããã
ãšããã§ã·ã³ã°ã«ã¹ã¬ãããªã©ããããªãã¿ãŒã³ã§ç¢ºèªããŠã¿ãã®ã§ãããããŒãžã§ã³4ã®UUIDçæã1çªé床ãåºãªãåŸåã«ããããã«
èŠããŸããã
ãããªãšããã§ã
ãŸãšã
Javaã®æšæºã©ã€ãã©ãªãŒã§äœ¿ãããšãã§ãããããŒãžã§ã³4以å€ã®UUIDãæ±ããã©ã€ãã©ãªãŒã調ã¹ã€ã€ãããããUUIDã«ã€ããŠã
å°ã調ã¹ãŠãŸãšããŠã¿ãŸããã
ããŒãžã§ã³6以éã®UUIDããã©ããã§ååšããããšã¯ç¥ã£ãŠããã®ã§ãããä»åã¡ãããšèŠãæ©äŒãäœã£ãŠãããŠããã£ãããªãšã
æ£åŒã«æ±ºãŸã£ãæã«ããŸããã£ããã¢ããããããšããã§ããã