欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

java代碼獲取UUID的實現(xiàn)示例

 更新時間:2023年06月02日 11:01:59   作者:西晉的no1  
本文主要介紹了java代碼獲取UUID的實現(xiàn)示例,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧

什么是UUID

UUID 是指(Universally Unique Identifier)通用唯一識別碼,128位。RFC 4122描述了具體的規(guī)范實現(xiàn)。

現(xiàn)實問題

我們開發(fā)的時候,數(shù)據(jù)庫表總會有一個主鍵,以前我們可能會使用自增的數(shù)字作為主鍵。這樣做去確實查詢的時候比較快, 但是在做系統(tǒng)集成或者數(shù)據(jù)遷移的的時候就麻煩了。這是id就有可能重復了。那么有什么比較好的方法解決這一問題呢? 于是jdk1.5出了UUID這個類來生成唯一的字符串標識。

UUID作用

UUID 的目的是讓分布式系統(tǒng)中的所有元素都能有唯一的識別信息。如此一來,每個人都可以創(chuàng)建不與其它人沖突的 UUID,就不需考慮數(shù)據(jù)庫創(chuàng)建時的名稱重復問題。其作用視場景而定。

目前最廣泛應用的 UUID,即是微軟的 Microsoft's Globally Unique Identifiers (GUIDs),而其他重要的應用, 則有 Linux ext2/ext3 檔案系統(tǒng)、LUKS 加密分割區(qū)、GNOME、KDE、Mac OS X 等等。

UUID定義

UUID使用16進制表示,共有36個字符(32個字母/數(shù)字+4個連接符"-")組成,格式為8-4-4-4-12 ;【一個字母/數(shù)字只代表4個bit,所以是(8+4+4+4+12)*4=128位;】

由一組32個16進制數(shù)碼(0-9a-z)所構(gòu)成,故 UUID 理論上的總數(shù)為,約等于

也就是說若每納秒產(chǎn)生1百萬個 UUID,要花100億年才會將所有 UUID 用完。

格式:

xxxxxxxx-xxxx-Mxxx-Nxxx-xxxxxxxxxxxx

示例:

96b31816-ae1c-11ed-904f-4531ee40a9e3

格式中M和N都有具體的含義

數(shù)字 M的四位表示 UUID 版本,當前規(guī)范有5個版本,M可選值為1, 2, 3, 4, 5 ;

數(shù)字 N的一至四個最高有效位表示 UUID 變體( variant ),有固定的兩位10xx因此只可能取值8, 9, a, b。

這5個版本使用不同算法,利用不同的信息來產(chǎn)生UUID,各版本有各自優(yōu)勢,適用于不同情景。具體使用的信息

  • 版本 1:UUID 是根據(jù)時間和 MAC 地址生成的;
  • 版本 2:UUID 是根據(jù)標識符(通常是組或用戶 ID)、時間和節(jié)點 ID生成的;
  • 版本 3:UUID 是通過散列(MD5 作為散列算法)名字空間(namespace)標識符和名稱生成的;
  • 版本 4:UUID 使用隨機性或偽隨機性生成;
  • 版本 5:類似于版本 3(SHA1 作為散列算法)。

故UUID每個版本不是根據(jù)精度區(qū)分的,Version5并不會比Version1精度高,在精度上,大家都能保證唯一性,重復的概率近乎于0。

為了能兼容過去的 UUID,以及應對未來的變化,因此有了變體(Variants)這一概念。

目前已知的變體有下面 4 種:

  • 變體 0:格式為 0xxx,為了向后兼容預留。
  • 變體 1:格式為 10xx,當前正在使用的。
  • 變體 2:格式為 11xx,為早期微軟的 GUID 預留。
  • 變體 3:格式為 111x,為將來的擴展預留,目前暫未使用。

在上例中,M 是 1,N 是 a(二進制為 1010,符合 10xx 的格式),這就意味著這個 UUID 是“版本 1”、“變體 1”的 UUID。

目前大多數(shù)使用的 UUID 大都是變體 1,N 的取值是 8、9、a、b 中的一個。

version 1——date-time & MAC address

基于時間戳及MAC地址的UUID實現(xiàn)。它包括了48位的MAC地址和60位的時間戳,

v1為了保證唯一性,當時間精度不夠時,會使用13~14位的clock sequence來擴展時間戳,比如:

當UUID的生產(chǎn)成速率太快,超過了系統(tǒng)時間的精度。時間戳的低位部分會每增加一個UUID就+1的操作來模擬更高精度的時間戳,換句話說,就是當系統(tǒng)時間精度無會區(qū)分2個UUID的時間先后時,為了保證唯一性,會在其中一個UUID上+1。所以UUID重復的概率幾乎為0,時間戳加擴展的clock sequence一共有74bits,(2的74次方,約為1.8后面加22個零),即在每個節(jié)點下,每秒可產(chǎn)生1630億不重復的UUID(因為只精確到了秒,不再是74位,所以換算了一下)。

相對于其它版本,v1還加入48位的MAC地址,這依賴于網(wǎng)卡供應商能提供唯一的MAC地址,同時也可能通過它反查到對應的MAC地址。Melissa病毒就是這樣做到的。

Version2(date-time Mac address)

這是最神秘的版本,RFC沒有提供具體的實現(xiàn)細節(jié),以至于大部分的UUID庫都沒有實現(xiàn)它,只在特定的場景(DCE security)才會用到。所以絕大數(shù)情況,我們也不會碰到它。

Version3,5(namespace name-based)

V3和V5都是通過hash namespace的標識符和名稱生成的。V3使用MD5作為hash函數(shù),V5則使用SHA-1。

因為里面沒有不確定的部分,所以當namespace與輸入?yún)?shù)確定時,得到的UUID都是確定唯一的。

具體的流程就是

把namespace和輸入?yún)?shù)拼接在一起,如"http/http://wwwbaidu.com" ++ "/query=uuid";

使用MD5算法對拼接后的字串進行hash,截斷為128位;

把UUID的Version和variant字段都替換成固定的;

如果需要to_string,需要轉(zhuǎn)為16進制和加上連接符"-"。

把V3的hash算法由MD5換成SHA-1就成了V5。

Version4(random)

這個版本使用最為廣泛:

其中4位代表版本,2-3位代表variant。余下的122-121位都是全部隨機的。即有2的122次方(5.3后面36個0)個UUID。一個標準實現(xiàn)的UUID庫在生成了2.71萬億個UUID會產(chǎn)生重復UUID的可能性也只有50%的概率:

這相當于每秒產(chǎn)生10億的UUID,持續(xù)85年,而把這些UUID都存入文件,每個UUID占16bytes,總需要45 EB(exabytes),比目前最大的數(shù)據(jù)庫(PB)還要大很多倍。

UUID的重復概率

Java中 UUID 使用版本4進行實現(xiàn),所以由java.util.UUID類產(chǎn)生的 UUID,128個比特中,有122個比特是隨機產(chǎn)生,4個比特標識版本被使用,還有2個標識變體被使用。利用生日悖論,可計算出兩筆 UUID 擁有相同值的機率約為

其中x為 UUID 的取值范圍,n為 UUID 的個數(shù)。

以下是以 x =

計算出n筆 UUID 后產(chǎn)生碰撞的機率:

換句話說,每秒產(chǎn)生10億筆 UUID ,100年后只產(chǎn)生一次重復的機率是50%。如果地球上每個人都各有6億筆 UUID,發(fā)生一次重復的機率是50%。與被隕石擊中的機率比較的話,已知一個人每年被隕石擊中的機率估計為170億分之1,也就是說機率大約是0.00000000006 (6 x ),等同于在一年內(nèi)生產(chǎn)2000億個 UUID 并發(fā)生一次重復。

Java獲取uuid示例

使用 JDK 原生的API

import java.util.UUID;
public class Test {
    public static void main(String[] args) {
        // JDK 原生的 API 獲取UUID
        // uuid版本3獲取uuid
        UUID uuid3 = UUID.nameUUIDFromBytes("test".getBytes());
        int version3 = uuid3.version();
        System.out.println("UUID3:" + uuid3 + " 版本 " + version3);
        // uuid版本4獲取uuid
        UUID uuid4 = UUID.randomUUID();
        int version4 = uuid4.version();
        System.out.println("UUID4:" + uuid4 + " 版本 " + version4);
        // 生成一個基于指定 UUID 字符串的 UUID 對象
        UUID uuid = UUID.fromString("098f6bcd-4621-3373-8ade-4e832627b4f6");
        int version = uuid.version();
        System.out.println("UUID_fromString:" + uuid + " 版本 " + version);
    }
}

nameUUIDFromBytes() 會生成一個版本 3 的UUID,不過需要傳遞一個名稱的字節(jié)數(shù)組作為參數(shù)。

randomUUID() 方法生成了一個版本 4 的 UUID,這也是生成 UUID最方便的方法。如果只使用原生 JDK 的話,基本上都用的這種方式。

fromString() 方法會生成一個基于指定 UUID 字符串的 UUID對象,如果指定的 UUID 字符串不符合 UUID 的格式,將拋出 IllegalArgumentException 異常。

使用com.fasterxml.uuid.Generators

除了使用 JDK 原生的 API 之外,還可以使用com.fasterxml.uuid.Generators,需要先在項目中加入該類的 Maven 依賴。

<dependencies>
<dependency>
<groupId>com.fasterxml.uuid</groupId>
<artifactId>java-uuid-generator</artifactId>
<version>3.1.4</version>
</dependency>
</dependencies>

代碼:

import com.fasterxml.uuid.Generators;
import java.util.UUID;
public class Test {
    public static void main(String[] args) {
        // JDK 原生的 API 獲取UUID
        // uuid版本1獲取uuid
        UUID uuid1 = Generators.timeBasedGenerator().generate();
        System.out.println("UUID : " + uuid1);
        System.out.println("UUID 版本 : " + uuid1.version());
        // uuid版本4獲取uuid
        UUID uuid2 = Generators.randomBasedGenerator().generate();
        System.out.println("UUID : " + uuid2);
        System.out.println("UUID 版本 : " + uuid2.version());
    }
}

Generators.timeBasedGenerator().generate() 可用于生成版本1 的 UUID,Generators.randomBasedGenerator().generate() 可用于生成版本4 的 UUID。

總結(jié)

使用較多的是版本1和版本4,其中版本1使用當前時間戳和MAC地址信息。版本4使用(偽)隨機數(shù)信息,128bit中,除去版本確定的4bit和variant確定的2bit,其它122bit全部由(偽)隨機數(shù)信息確定。

因為時間戳和隨機數(shù)的唯一性,版本1和版本4總是生成唯一的標識符。若希望對給定的一個字符串總是能生成相同的 UUID,使用版本3或版本5。如果只是需要生成一個唯一ID,你可以使用V1或V4。

- V1基于時間戳和Mac地址,這些ID有一定的規(guī)律(你給出一個,是有可能被猜出來下一個是多少的),而且會暴露你的Mac地址。

- V4是完全隨機(偽)的。

如果對于相同的參數(shù)需要輸出相同的UUID,你可以使用V3或V5。

- V3基于MD5 hash算法,如果需要考慮與其它系統(tǒng)的兼容性的話,就用它,因為它出來得早,大概率大家都是用它的。

- V5基于SHA-1 hash算法,這個是首選。

到此這篇關(guān)于java代碼獲取UUID的實現(xiàn)示例的文章就介紹到這了,更多相關(guān)java獲取UUID內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Java計算字符串公式的方式解讀

    Java計算字符串公式的方式解讀

    這篇文章主要介紹了Java計算字符串公式的方式解讀,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-12-12
  • Springboot源碼 TargetSource解析

    Springboot源碼 TargetSource解析

    這篇文章主要介紹了Springboot源碼 TargetSource解析,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下
    2019-08-08
  • 詳解Java單例模式中的餓漢和懶漢模式

    詳解Java單例模式中的餓漢和懶漢模式

    這篇文章主要介紹了詳解Java單例模式中的餓漢和懶漢模式,單例模式中有兩種模式一種是餓漢模式,一種是懶漢模式,那么他們有什么區(qū)別呢,需要的朋友可以參考下本文
    2023-04-04
  • Java?SE使用for?each循環(huán)遍歷數(shù)組的方法代碼

    Java?SE使用for?each循環(huán)遍歷數(shù)組的方法代碼

    在Java?SE開發(fā)中,數(shù)組是最常見的數(shù)據(jù)結(jié)構(gòu)之一,Java提供了多種遍歷數(shù)組的方式,其中for循環(huán)是最常用的方式之一,本文將介紹如何使用for?each循環(huán)遍歷數(shù)組,接下來,我們將通過一個簡單的代碼示例來展示如何使用for?each循環(huán)遍歷數(shù)組,需要的朋友可以參考下
    2023-11-11
  • Java遞歸運行的機制:遞歸的微觀解讀圖文分析

    Java遞歸運行的機制:遞歸的微觀解讀圖文分析

    這篇文章主要介紹了Java遞歸運行的機制:遞歸的微觀解讀,結(jié)合圖文形式詳細分析了java遞歸運行的原理、機制與相關(guān)注意事項,需要的朋友可以參考下
    2020-03-03
  • SpringBoot基于數(shù)據(jù)庫的定時任務統(tǒng)一管理的實現(xiàn)

    SpringBoot基于數(shù)據(jù)庫的定時任務統(tǒng)一管理的實現(xiàn)

    這篇文章主要介紹了SpringBoot基于數(shù)據(jù)庫的定時任務統(tǒng)一管理的實現(xiàn),文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2019-12-12
  • 解析Spring?漏洞及其修復方案

    解析Spring?漏洞及其修復方案

    官宣了最近網(wǎng)傳的Spring漏洞。攻擊者利用該漏洞,可在未授權(quán)的情況下遠程執(zhí)行命令,今天通過本文給大家普及下漏洞分析影響范圍及解決方案,感興趣的朋友跟隨小編一起看看吧
    2022-04-04
  • java開發(fā)BeanUtils類解決實體對象間賦值

    java開發(fā)BeanUtils類解決實體對象間賦值

    這篇文章主要為大家介紹了java開發(fā)中使用BeanUtils類實現(xiàn)實體對象之間的賦值有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步學有所得
    2021-10-10
  • Java-性能分析和監(jiān)控工具深入詳解

    Java-性能分析和監(jiān)控工具深入詳解

    這篇文章主要介紹了Java-性能分析和監(jiān)控工具深入詳解,文章內(nèi)容詳細,簡單易懂,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2023-01-01
  • MyBatis實現(xiàn)樂觀鎖和悲觀鎖的示例代碼

    MyBatis實現(xiàn)樂觀鎖和悲觀鎖的示例代碼

    在數(shù)據(jù)庫操作中,樂觀鎖和悲觀鎖是兩種常見的并發(fā)控制策略,本文主要介紹了MyBatis實現(xiàn)樂觀鎖和悲觀鎖的示例代碼,具有一定的參考價值,感興趣的可以了解一下
    2024-07-07

最新評論