日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > java >内容正文

java

Java中使用UUID工具类生成唯一标志防止重复

發布時間:2025/3/19 java 41 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Java中使用UUID工具类生成唯一标志防止重复 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

場景

UUID 是指Universally Unique Identifier,翻譯為中文是通用唯一識別碼,UUID 的目的是讓分布式系統中的所有元素都能有唯一的識別信息。

在某些場景下需要給數據庫中存儲的某些字段使用唯一標志。

或者需要一些唯一標志的字符串。

注:

博客:
https://blog.csdn.net/badao_liumang_qizhi
關注公眾號
霸道的程序猿
獲取編程相關電子書、教程推送與免費下載。

實現

首先新建一個ID生成器工具類IdUtils

/*** ID生成器工具類*/ public class IdUtils {/*** 獲取隨機UUID** @return 隨機UUID*/public static String randomUUID(){return UUID.randomUUID().toString();}/*** 簡化的UUID,去掉了橫線** @return 簡化的UUID,去掉了橫線*/public static String simpleUUID(){return UUID.randomUUID().toString(true);}/*** 獲取隨機UUID,使用性能更好的ThreadLocalRandom生成UUID** @return 隨機UUID*/public static String fastUUID(){return UUID.fastUUID().toString();}/*** 簡化的UUID,去掉了橫線,使用性能更好的ThreadLocalRandom生成UUID** @return 簡化的UUID,去掉了橫線*/public static String fastSimpleUUID(){return UUID.fastUUID().toString(true);} }

在這個工具類中調用了UUID這個實現類的一些方法

UUID.java

import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import java.security.SecureRandom; import java.util.Random; import java.util.concurrent.ThreadLocalRandom;/*** 提供通用唯一識別碼(universally unique identifier)(UUID)實現**/ public final class UUID implements java.io.Serializable, Comparable<UUID> {private static final long serialVersionUID = -1185015143654744140L;/*** SecureRandom 的單例**/private static class Holder{static final SecureRandom numberGenerator = getSecureRandom();}/** 此UUID的最高64有效位 */private final long mostSigBits;/** 此UUID的最低64有效位 */private final long leastSigBits;/*** 私有構造** @param data 數據*/private UUID(byte[] data){long msb = 0;long lsb = 0;assert data.length == 16 : "data must be 16 bytes in length";for (int i = 0; i < 8; i++){msb = (msb << 8) | (data[i] & 0xff);}for (int i = 8; i < 16; i++){lsb = (lsb << 8) | (data[i] & 0xff);}this.mostSigBits = msb;this.leastSigBits = lsb;}/*** 使用指定的數據構造新的 UUID。** @param mostSigBits 用于 {@code UUID} 的最高有效 64 位* @param leastSigBits 用于 {@code UUID} 的最低有效 64 位*/public UUID(long mostSigBits, long leastSigBits){this.mostSigBits = mostSigBits;this.leastSigBits = leastSigBits;}/*** 獲取類型 4(偽隨機生成的)UUID 的靜態工廠。 使用加密的本地線程偽隨機數生成器生成該 UUID。** @return 隨機生成的 {@code UUID}*/public static UUID fastUUID(){return randomUUID(false);}/*** 獲取類型 4(偽隨機生成的)UUID 的靜態工廠。 使用加密的強偽隨機數生成器生成該 UUID。** @return 隨機生成的 {@code UUID}*/public static UUID randomUUID(){return randomUUID(true);}/*** 獲取類型 4(偽隨機生成的)UUID 的靜態工廠。 使用加密的強偽隨機數生成器生成該 UUID。** @param isSecure 是否使用{@link SecureRandom}如果是可以獲得更安全的隨機碼,否則可以得到更好的性能* @return 隨機生成的 {@code UUID}*/public static UUID randomUUID(boolean isSecure){final Random ng = isSecure ? Holder.numberGenerator : getRandom();byte[] randomBytes = new byte[16];ng.nextBytes(randomBytes);randomBytes[6] &= 0x0f; /* clear version */randomBytes[6] |= 0x40; /* set to version 4 */randomBytes[8] &= 0x3f; /* clear variant */randomBytes[8] |= 0x80; /* set to IETF variant */return new UUID(randomBytes);}/*** 根據指定的字節數組獲取類型 3(基于名稱的)UUID 的靜態工廠。** @param name 用于構造 UUID 的字節數組。** @return 根據指定數組生成的 {@code UUID}*/public static UUID nameUUIDFromBytes(byte[] name){MessageDigest md;try{md = MessageDigest.getInstance("MD5");}catch (NoSuchAlgorithmException nsae){throw new InternalError("MD5 not supported");}byte[] md5Bytes = md.digest(name);md5Bytes[6] &= 0x0f; /* clear version */md5Bytes[6] |= 0x30; /* set to version 3 */md5Bytes[8] &= 0x3f; /* clear variant */md5Bytes[8] |= 0x80; /* set to IETF variant */return new UUID(md5Bytes);}/*** 根據 {@link #toString()} 方法中描述的字符串標準表示形式創建{@code UUID}。** @param name 指定 {@code UUID} 字符串* @return 具有指定值的 {@code UUID}* @throws IllegalArgumentException 如果 name 與 {@link #toString} 中描述的字符串表示形式不符拋出此異常**/public static UUID fromString(String name){String[] components = name.split("-");if (components.length != 5){throw new IllegalArgumentException("Invalid UUID string: " + name);}for (int i = 0; i < 5; i++){components[i] = "0x" + components[i];}long mostSigBits = Long.decode(components[0]).longValue();mostSigBits <<= 16;mostSigBits |= Long.decode(components[1]).longValue();mostSigBits <<= 16;mostSigBits |= Long.decode(components[2]).longValue();long leastSigBits = Long.decode(components[3]).longValue();leastSigBits <<= 48;leastSigBits |= Long.decode(components[4]).longValue();return new UUID(mostSigBits, leastSigBits);}/*** 返回此 UUID 的 128 位值中的最低有效 64 位。** @return 此 UUID 的 128 位值中的最低有效 64 位。*/public long getLeastSignificantBits(){return leastSigBits;}/*** 返回此 UUID 的 128 位值中的最高有效 64 位。** @return 此 UUID 的 128 位值中最高有效 64 位。*/public long getMostSignificantBits(){return mostSigBits;}/*** 與此 {@code UUID} 相關聯的版本號. 版本號描述此 {@code UUID} 是如何生成的。* <p>* 版本號具有以下含意:* <ul>* <li>1 基于時間的 UUID* <li>2 DCE 安全 UUID* <li>3 基于名稱的 UUID* <li>4 隨機生成的 UUID* </ul>** @return 此 {@code UUID} 的版本號*/public int version(){// Version is bits masked by 0x000000000000F000 in MS longreturn (int) ((mostSigBits >> 12) & 0x0f);}/*** 與此 {@code UUID} 相關聯的變體號。變體號描述 {@code UUID} 的布局。* <p>* 變體號具有以下含意:* <ul>* <li>0 為 NCS 向后兼容保留* <li>2 <a href="IETF&nbsp;RFC&nbsp;4122(Leach-Salz'" DESIGNTIMESP=969>IETF&nbsp;RFC&nbsp;4122(Leach-Salz'" DESIGNTIMESP=518>http://www.ietf.org/rfc/rfc4122.txt">IETF&nbsp;RFC&nbsp;4122</a>(Leach-Salz), 用于此類* <li>6 保留,微軟向后兼容* <li>7 保留供以后定義使用* </ul>** @return 此 {@code UUID} 相關聯的變體號*/public int variant(){// This field is composed of a varying number of bits.// 0 - - Reserved for NCS backward compatibility// 1 0 - The IETF aka Leach-Salz variant (used by this class)// 1 1 0 Reserved, Microsoft backward compatibility// 1 1 1 Reserved for future definition.return (int) ((leastSigBits >>> (64 - (leastSigBits >>> 62))) & (leastSigBits >> 63));}/*** 與此 UUID 相關聯的時間戳值。** <p>* 60 位的時間戳值根據此 {@code UUID} 的 time_low、time_mid 和 time_hi 字段構造。<br>* 所得到的時間戳以 100 毫微秒為單位,從 UTC(通用協調時間) 1582 年 10 月 15 日零時開始。** <p>* 時間戳值僅在在基于時間的 UUID(其 version 類型為 1)中才有意義。<br>* 如果此 {@code UUID} 不是基于時間的 UUID,則此方法拋出 UnsupportedOperationException。** @throws UnsupportedOperationException 如果此 {@code UUID} 不是 version 為 1 的 UUID。*/public long timestamp() throws UnsupportedOperationException{checkTimeBase();return (mostSigBits & 0x0FFFL) << 48//| ((mostSigBits >> 16) & 0x0FFFFL) << 32//| mostSigBits >>> 32;}/*** 與此 UUID 相關聯的時鐘序列值。** <p>* 14 位的時鐘序列值根據此 UUID 的 clock_seq 字段構造。clock_seq 字段用于保證在基于時間的 UUID 中的時間唯一性。* <p>* {@code clockSequence} 值僅在基于時間的 UUID(其 version 類型為 1)中才有意義。 如果此 UUID 不是基于時間的 UUID,則此方法拋出* UnsupportedOperationException。** @return 此 {@code UUID} 的時鐘序列** @throws UnsupportedOperationException 如果此 UUID 的 version 不為 1*/public int clockSequence() throws UnsupportedOperationException{checkTimeBase();return (int) ((leastSigBits & 0x3FFF000000000000L) >>> 48);}/*** 與此 UUID 相關的節點值。** <p>* 48 位的節點值根據此 UUID 的 node 字段構造。此字段旨在用于保存機器的 IEEE 802 地址,該地址用于生成此 UUID 以保證空間唯一性。* <p>* 節點值僅在基于時間的 UUID(其 version 類型為 1)中才有意義。<br>* 如果此 UUID 不是基于時間的 UUID,則此方法拋出 UnsupportedOperationException。** @return 此 {@code UUID} 的節點值** @throws UnsupportedOperationException 如果此 UUID 的 version 不為 1*/public long node() throws UnsupportedOperationException{checkTimeBase();return leastSigBits & 0x0000FFFFFFFFFFFFL;}/*** 返回此{@code UUID} 的字符串表現形式。** <p>* UUID 的字符串表示形式由此 BNF 描述:** <pre>* {@code* UUID?????????????????? = <time_low>-<time_mid>-<time_high_and_version>-<variant_and_sequence>-<node>* time_low?????????????? = 4*<hexOctet>* time_mid?????????????? = 2*<hexOctet>* time_high_and_version? = 2*<hexOctet>* variant_and_sequence?? = 2*<hexOctet>* node?????????????????? = 6*<hexOctet>* hexOctet?????????????? = <hexDigit><hexDigit>* hexDigit?????????????? = [0-9a-fA-F]* }* </pre>** </blockquote>** @return 此{@code UUID} 的字符串表現形式* @see #toString(boolean)*/@Overridepublic String toString(){return toString(false);}/*** 返回此{@code UUID} 的字符串表現形式。** <p>* UUID 的字符串表示形式由此 BNF 描述:** <pre>* {@code* UUID?????????????????? = <time_low>-<time_mid>-<time_high_and_version>-<variant_and_sequence>-<node>* time_low?????????????? = 4*<hexOctet>* time_mid?????????????? = 2*<hexOctet>* time_high_and_version? = 2*<hexOctet>* variant_and_sequence?? = 2*<hexOctet>* node?????????????????? = 6*<hexOctet>* hexOctet?????????????? = <hexDigit><hexDigit>* hexDigit?????????????? = [0-9a-fA-F]* }* </pre>** </blockquote>** @param isSimple 是否簡單模式,簡單模式為不帶'-'的UUID字符串* @return 此{@code UUID} 的字符串表現形式*/public String toString(boolean isSimple){final StringBuilder builder = new StringBuilder(isSimple ? 32 : 36);// time_lowbuilder.append(digits(mostSigBits >> 32, 8));if (false == isSimple){builder.append('-');}// time_midbuilder.append(digits(mostSigBits >> 16, 4));if (false == isSimple){builder.append('-');}// time_high_and_versionbuilder.append(digits(mostSigBits, 4));if (false == isSimple){builder.append('-');}// variant_and_sequencebuilder.append(digits(leastSigBits >> 48, 4));if (false == isSimple){builder.append('-');}// nodebuilder.append(digits(leastSigBits, 12));return builder.toString();}/*** 返回此 UUID 的哈希碼。** @return UUID 的哈希碼值。*/@Overridepublic int hashCode(){long hilo = mostSigBits ^ leastSigBits;return ((int) (hilo >> 32)) ^ (int) hilo;}/*** 將此對象與指定對象比較。* <p>* 當且僅當參數不為 {@code null}、而是一個 UUID 對象、具有與此 UUID 相同的 varriant、包含相同的值(每一位均相同)時,結果才為 {@code true}。** @param obj 要與之比較的對象** @return 如果對象相同,則返回 {@code true};否則返回 {@code false}*/@Overridepublic boolean equals(Object obj){if ((null == obj) || (obj.getClass() != UUID.class)){return false;}UUID id = (UUID) obj;return (mostSigBits == id.mostSigBits && leastSigBits == id.leastSigBits);}// Comparison Operations/*** 將此 UUID 與指定的 UUID 比較。** <p>* 如果兩個 UUID 不同,且第一個 UUID 的最高有效字段大于第二個 UUID 的對應字段,則第一個 UUID 大于第二個 UUID。** @param val 與此 UUID 比較的 UUID** @return 在此 UUID 小于、等于或大于 val 時,分別返回 -1、0 或 1。**/@Overridepublic int compareTo(UUID val){// The ordering is intentionally set up so that the UUIDs// can simply be numerically compared as two numbersreturn (this.mostSigBits < val.mostSigBits ? -1 : //(this.mostSigBits > val.mostSigBits ? 1 : //(this.leastSigBits < val.leastSigBits ? -1 : //(this.leastSigBits > val.leastSigBits ? 1 : //0))));}// -------------------------------------------------------------------------------------------------------------------// Private method start/*** 返回指定數字對應的hex值** @param val 值* @param digits 位* @return 值*/private static String digits(long val, int digits){long hi = 1L << (digits * 4);return Long.toHexString(hi | (val & (hi - 1))).substring(1);}/*** 檢查是否為time-based版本UUID*/private void checkTimeBase(){if (version() != 1){throw new UnsupportedOperationException("Not a time-based UUID");}}/*** 獲取{@link SecureRandom},類提供加密的強隨機數生成器 (RNG)** @return {@link SecureRandom}*/public static SecureRandom getSecureRandom(){try{return SecureRandom.getInstance("SHA1PRNG");}catch (NoSuchAlgorithmException e){throw new UtilException(e);}}/*** 獲取隨機數生成器對象<br>* ThreadLocalRandom是JDK 7之后提供并發產生隨機數,能夠解決多個線程發生的競爭爭奪。** @return {@link ThreadLocalRandom}*/public static ThreadLocalRandom getRandom(){return ThreadLocalRandom.current();} }

這其中又使用了自定義異常類UtilException

public class UtilException extends RuntimeException {private static final long serialVersionUID = 8247610319171014183L;public UtilException(Throwable e){super(e.getMessage(), e);}public UtilException(String message){super(message);}public UtilException(String message, Throwable throwable){super(message, throwable);} }

使用示例

String uuid = IdUtils.simpleUUID();

?

總結

以上是生活随笔為你收集整理的Java中使用UUID工具类生成唯一标志防止重复的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。