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

Java生成唯一ID的三種方法總結(jié)

 更新時間:2024年09月21日 10:29:23   作者:長腿大壯  
單機(jī)環(huán)境下,可以使用AtomicLong來生成唯一ID;而在需要非純數(shù)字形式的場景中,可以通過UUID結(jié)合哈希函數(shù)如MD5或SHA-1轉(zhuǎn)換成數(shù)字,但需注意哈希碰撞的低概率風(fēng)險;對于分布式系統(tǒng),模擬Snowflake算法是一種復(fù)雜但有效的方法,每種方法都有其適用場景和潛在問題

使用AtomicLong生成唯一ID(適用于單機(jī)場景)

這個示例已經(jīng)在之前的回答中給出,但我會再次展示它,以便與后續(xù)示例保持連貫性。

import java.util.concurrent.atomic.AtomicLong;  
  
public class UniqueIdGenerator {  
    private final AtomicLong counter = new AtomicLong(0);  
  
    public long nextId() {  
        return counter.incrementAndGet();  
    }  
  
    public static void main(String[] args) {  
        UniqueIdGenerator generator = new UniqueIdGenerator();  
        long id1 = generator.nextId();  
        long id2 = generator.nextId();  
        System.out.println("ID 1: " + id1);  
        System.out.println("ID 2: " + id2);  
    }  
}

使用UUID并轉(zhuǎn)換為數(shù)字形式(雖然不是純數(shù)字,但提供了唯一性)

由于UUID本身是字符串形式的,我們可以通過哈希函數(shù)(如MD5、SHA-1等)將其轉(zhuǎn)換為數(shù)字,但需要注意哈希碰撞的可能性(盡管在實際應(yīng)用中非常低)。然而,更常見的是保留UUID的字符串形式或使用其作為基礎(chǔ)來生成符合特定需求的數(shù)字ID。

import java.util.UUID;  
  
public class UuidToNumberExample {  
    // 注意:這不是將UUID直接轉(zhuǎn)換為唯一數(shù)字的有效方法,因為存在哈希碰撞的風(fēng)險。  
    // 這里只是為了說明概念。  
  
    public static long uuidToNumber(UUID uuid) {  
        // 簡單的示例:將UUID的字符串表示形式與另一個數(shù)字組合,然后進(jìn)行哈希(注意:這不是安全的做法)  
        String uuidStr = uuid.toString();  
        long base = 123456789L; // 假設(shè)的基數(shù)  
        // 這里不實現(xiàn)哈希函數(shù),而是使用字符串長度加基數(shù)作為示例(僅為演示)  
        return uuidStr.length() + base; // 這不是一個好的實現(xiàn)!  
  
        // 更實際的方法是使用安全的哈希函數(shù),但請注意哈希碰撞的可能性  
        // 并且,由于哈希函數(shù)的輸出是固定長度的,直接用作ID可能需要進(jìn)一步處理  
    }  
  
    public static void main(String[] args) {  
        UUID uuid = UUID.randomUUID();  
        long number = uuidToNumber(uuid); // 這里的實現(xiàn)是錯誤的,僅用于說明  
        System.out.println("UUID: " + uuid);  
        System.out.println("Converted Number (Incorrect Method): " + number);  
  
        // 正確的做法可能是將UUID用作查找或生成更復(fù)雜ID的基礎(chǔ)  
    }  
}

模擬Snowflake算法生成唯一ID(分布式場景)

Snowflake算法的實現(xiàn)相對復(fù)雜,但我們可以簡化其核心思想來展示一個基本框架。

public class SnowflakeIdWorker {  
    // 假設(shè)的時間戳、數(shù)據(jù)中心ID、機(jī)器ID和序列號字段(實際應(yīng)用中需要更精細(xì)的管理)  
    private final long twepoch = 1288834974657L; // 自定義起始時間戳  
    private final long datacenterIdBits = 5L; // 數(shù)據(jù)中心ID位數(shù)  
    private final long maxDatacenterId = -1L ^ (-1L << datacenterIdBits); // 數(shù)據(jù)中心ID最大值  
    private final long workerIdBits = 5L; // 機(jī)器ID位數(shù)  
    private final long maxWorkerId = -1L ^ (-1L << workerIdBits); // 機(jī)器ID最大值  
    private final long sequenceBits = 12L; // 序列號位數(shù)  
  
    private final long workerIdShift = sequenceBits; // 機(jī)器ID左移位數(shù)  
    private final long datacenterIdShift = sequenceBits + workerIdBits; // 數(shù)據(jù)中心ID左移位數(shù)  
    private final long timestampLeftShift = sequenceBits + workerIdBits + datacenterIdBits; // 時間戳左移位數(shù)  
  
    private long sequence = 0L; // 序列號  
    private long lastTimestamp = -1L; // 上次生成ID的時間戳  
  
    // 構(gòu)造函數(shù)中初始化workerId和datacenterId(這里為示例,實際中應(yīng)由外部指定)  
    public SnowflakeIdWorker(long workerId, long datacenterId) {  
        if (workerId > maxWorkerId || workerId < 0) {  
            throw new IllegalArgumentException(String.format("worker Id can't be greater than %d or less than 0", maxWorkerId));  
        }  
        if (datacenterId > maxDatacenterId || datacenterId < 0) {  
            throw new IllegalArgumentException(String.format("datacenter Id can't be greater than %d or less than 0", maxDatacenterId));  
        }  
        // 這里省略了實際將workerId和datacenterId設(shè)置到對象中的步驟  
    }  
  
    // 生成ID的方法(簡化版,未包含時鐘回?fù)芴幚淼龋? 
    public synchronized long nextId() {  
        long timestamp = timeGen();  
  
        // 如果當(dāng)前時間小于上一次ID生成的時間戳,說明系統(tǒng)時鐘回?fù)苓^  
        if (timestamp < lastTimestamp) {  
            throw new RuntimeException(String.format("Clock moved backwards. Refusing to generate id for %d milliseconds", lastTimestamp - timestamp));  
        }  
  
        // 如果是同一時間生成的,則進(jìn)行毫秒內(nèi)序列  
        if (lastTimestamp == timestamp) {  
            sequence = (sequence + 1) & (-1L ^ (-1L << sequenceBits));  
            if (sequence == 0) {  
                // 毫秒內(nèi)序列溢出  
                timestamp = tilNextMillis(lastTimestamp);  
            }  
        } else {  
            // 時間戳改變,毫秒內(nèi)序列重置  
            sequence = 0L;  
        }  
  
        // 上次生成ID的時間戳  
        lastTimestamp = timestamp;  
  
        // 移位并通過或運(yùn)算拼到一起組成64位的ID  
        // 這里省略了實際的workerId和datacenterId的左移和或操作  
        // 示例:return ((timestamp - twepoch) << timestampLeftShift) | (datacenterId << datacenterIdShift) | (workerId << workerIdShift) | sequence;  
        return 0L; // 返回模擬的0,實際應(yīng)返回通過上述方式計算的ID  
    }  
  
    // 模擬獲取系統(tǒng)當(dāng)前時間戳(毫秒)  
    protected long timeGen() {  
        return System.currentTimeMillis();  
    }  
  
    // 等待到下一個毫秒,獲得新的時間戳  
    protected long tilNextMillis(long lastTimestamp) {  
        long timestamp = timeGen();  
        while (timestamp <= lastTimestamp) {  
            timestamp = timeGen();  
        }  
        return timestamp;  
    }  
  
    // 省略main方法和其他可能的輔助方法...  
}

請注意,上述Snowflake算法的實現(xiàn)是高度簡化的,并省略了許多關(guān)鍵細(xì)節(jié)(如實際的數(shù)據(jù)中心ID和機(jī)器ID的設(shè)置、序列號的正確處理以及時鐘回?fù)艿脑敿?xì)處理邏輯)。在實際應(yīng)用中,您需要根據(jù)自己的需求和環(huán)境來完整實現(xiàn)這些功能。

總結(jié)

在單機(jī)環(huán)境下,可以使用AtomicLong來生成唯一ID;而在需要非純數(shù)字形式的場景中,可以通過UUID結(jié)合哈希函數(shù)如MD5或SHA-1轉(zhuǎn)換成數(shù)字,但需注意哈希碰撞的低概率風(fēng)險;對于分布式系統(tǒng),模擬Snowflake算法是一種復(fù)雜但有效的方法,每種方法都有其適用場景和潛在問題,需要根據(jù)具體需求和環(huán)境選擇合適的實現(xiàn)方式。

到此這篇關(guān)于Java生成唯一ID的三種方法總結(jié)的文章就介紹到這了,更多相關(guān)Java生成唯一ID內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • java實現(xiàn)多選批量刪除功能

    java實現(xiàn)多選批量刪除功能

    工作中批量刪除可以提高我們的工作效率,今天這篇文章主要介紹了java實現(xiàn)多選批量刪除功能,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2021-08-08
  • Mybatis不支持batchInsertOrUpdate返顯id問題

    Mybatis不支持batchInsertOrUpdate返顯id問題

    這篇文章主要介紹了Mybatis不支持batchInsertOrUpdate返顯id問題,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2024-05-05
  • 使用@DS輕松解決動態(tài)數(shù)據(jù)源的問題

    使用@DS輕松解決動態(tài)數(shù)據(jù)源的問題

    這篇文章主要介紹了使用@DS輕松解決動態(tài)數(shù)據(jù)源的問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-05-05
  • Java?Stream.reduce()用法詳細(xì)解析

    Java?Stream.reduce()用法詳細(xì)解析

    Stream API提供了豐富的中間函數(shù),歸并函數(shù)和終端函數(shù),這些函數(shù)還支持并行化執(zhí)行,下面這篇文章主要給大家介紹了關(guān)于Java?Stream.reduce()用法的相關(guān)資料,需要的朋友可以參考下
    2022-12-12
  • springmvc接口接收參數(shù)與請求參數(shù)格式的整理

    springmvc接口接收參數(shù)與請求參數(shù)格式的整理

    這篇文章主要介紹了springmvc接口接收參數(shù)與請求參數(shù)格式的整理,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2021-11-11
  • JAVA如何讀取Excel數(shù)據(jù)

    JAVA如何讀取Excel數(shù)據(jù)

    這篇文章主要介紹了JAVA如何讀取Excel數(shù)據(jù),幫助大家更好的理解和學(xué)習(xí)Java,感興趣的朋友可以了解下
    2020-09-09
  • Java實現(xiàn)調(diào)用jython執(zhí)行python文件的方法

    Java實現(xiàn)調(diào)用jython執(zhí)行python文件的方法

    這篇文章主要介紹了Java實現(xiàn)調(diào)用jython執(zhí)行python文件的方法,結(jié)合實例形式分析了Java調(diào)用jython執(zhí)行python文件的常見操作技巧及相關(guān)問題解決方法,需要的朋友可以參考下
    2018-03-03
  • Java經(jīng)典排序算法之插入排序代碼實例

    Java經(jīng)典排序算法之插入排序代碼實例

    這篇文章主要介紹了Java經(jīng)典排序算法之插入排序代碼實例,插入排序是一種最簡單直觀的排序算法,它的工作原理是通過構(gòu)建有序序列,對于未排序數(shù)據(jù),在已排序序列中從后向前掃描,找到相應(yīng)位置并插入,需要的朋友可以參考下
    2023-10-10
  • 深入了解Java中的static關(guān)鍵字

    深入了解Java中的static關(guān)鍵字

    這篇文章主要為大家詳細(xì)介紹了Java中的static關(guān)鍵字的用法的相關(guān)資料,文中的示例代碼講解詳細(xì),具有一定的借鑒價值,感興趣的小伙伴可以學(xué)習(xí)一下
    2022-11-11
  • springboot中如何替換class文件

    springboot中如何替換class文件

    這篇文章主要介紹了springboot中如何替換class文件,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2023-02-02

最新評論