java常用工具类:生成唯一id
java常用工具类
1.java常用工具类:java实现Excel文件上传下载(模板)-hutool_hutool做excel下载-CSDN博客
2.java常用工具类:java实现excel模板导入数据,允许模板中部分数据字段为空_java导入excel,字段不能为空-CSDN博客
3.使用pinyin4j库实现中文转拼音-CSDN博客
4.java常用工具类:java实现Excel导入和导出_java 导出带参数-CSDN博客
5.java常用工具类:vue+java+aes进行加密解密(ECB、CBC模式)_vue aes加密 java解密-CSDN博客
6.java常用工具类:实现base64加盐编码、解码-CSDN博客
7.java常用工具类:判断对象中属性全是否为空-CSDN博客
8.java常用工具类:实现文件下载-CSDN博客
9.java常用工具类:计算文件大小-CSDN博客
10.java常用工具类:调用第三方接口-CSDN博客
11.java常用工具类:实现MD5加密(加盐)-CSDN博客
12.java常用工具类:生成唯一id-CSDN博客
方式一:UUID
UUID(Universally Unique Identifier)是一种广泛使用的唯一标识符生成方式。Java内置了对UUID的支持,我们可以直接使用java.util.UUID
类来生成。
import java.util.UUID;public class UUIDGenerator {public static void main(String[] args) {UUID uniqueID = UUID.randomUUID();System.out.println("UUID: " + uniqueID.toString());}
}
UUID的优点是全局唯一,但缺点是长度较长,不便于阅读。
方式二:自定义UUID
import java.util.Random;/*** @Author majinzhong* @Date 2024/4/29 16:34* @Version 1.0*/
public class UidUtil {/*** 创建自定义UUID* @param begin uuid开头* @param length 长度* @return*/public static String genCodes(String begin,int length){String front=begin;String val = "";Random random = new Random();for(int i = 0; i < length; i++){String charOrNum = random.nextInt(2) % 2 == 0 ? "char" : "num"; // 输出字母还是数字if("char".equalsIgnoreCase(charOrNum)) // 字符串{int choice = random.nextInt(2) % 2 == 0 ? 65 : 97; //取得大写字母还是小写字母val += (char) (choice + random.nextInt(26));} else if("num".equalsIgnoreCase(charOrNum)) // 数字{val += String.valueOf(random.nextInt(10));}}front=front+val.toLowerCase();return front;}
}
自定义UUID,可以设置UUID的开头,也可以设置长度
方式三:使用Snowflake算法
Snowflake算法是一种由Twitter开源的分布式ID生成算法,它能够生成64位的长整型ID。这个ID由41位的时间戳、5位的机器标识位、12位的序列号组成。
public class SnowflakeIdWorker {// ==============================Fields===========================================/** 开始时间截 (2015-01-01) */private final long twepoch = 1420041600000L;/** 机器id所占的位数 */private final long workerIdBits = 5L;/** 数据标识id所占的位数 */private final long datacenterIdBits = 5L;/** 支持的最大机器id,结果是31 (这个移位算法可以很快的计算出几位二进制数所能表示的最大十进制数) */private final long maxWorkerId = -1L ^ (-1L << workerIdBits);/** 支持的最大数据标识id,结果是31 */private final long maxDatacenterId = -1L ^ (-1L << datacenterIdBits);/** 序列在id中占的位数 */private final long sequenceBits = 12L;/** 机器ID向左移12位 */private final long workerIdShift = sequenceBits;/** 数据标识id向左移17位(12+5) */private final long datacenterIdShift = sequenceBits + workerIdBits;/** 时间截向左移22位(5+5+12) */private final long timestampLeftShift = sequenceBits + workerIdBits + datacenterIdBits;/** 生成序列的掩码,这里为4095 (0b111111111111=0xfff=4095) */private final long sequenceMask = -1L ^ (-1L << sequenceBits);/** 工作机器ID(0~31) */private long workerId;/** 数据中心ID(0~31) */private long datacenterId;/** 毫秒内序列(0~4095) */private long sequence = 0L;/** 上次生成ID的时间截 */private long lastTimestamp = -1L;//==============================Constructors=====================================/*** 构造函数* @param workerId 工作ID (0~31)* @param datacenterId 数据中心ID (0~31)*/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));}this.workerId = workerId;this.datacenterId = datacenterId;}// ==============================Methods==========================================/*** 获得下一个ID (该方法是线程安全的)* @return SnowflakeId*/public synchronized long nextId() {long timestamp = timeGen();//如果当前时间小于上一次ID生成的时间戳,说明系统时钟回退过这个时候应当抛出异常if (timestamp < lastTimestamp) {throw new RuntimeException(String.format("Clock moved backwards. Refusing to generate id for %d milliseconds", lastTimestamp - timestamp));}//如果是同一时间生成的,则进行毫秒内序列if (lastTimestamp == timestamp) {sequence = (sequence + 1) & sequenceMask;//毫秒内序列溢出if (sequence == 0) {//阻塞到下一个毫秒,获得新的时间戳timestamp = tilNextMillis(lastTimestamp);}}//时间戳改变,毫秒内序列重置else {sequence = 0L;}//上次生成ID的时间截lastTimestamp = timestamp;//移位并通过或运算拼到一起组成64位的IDreturn ((timestamp - twepoch) << timestampLeftShift) //| (datacenterId << datacenterIdShift) //| (workerId << workerIdShift) //| sequence;}/*** 阻塞到下一个毫秒,直到获得新的时间戳* @param lastTimestamp 上次生成ID的时间截* @return 当前时间戳*/protected long tilNextMillis(long lastTimestamp) {long timestamp = timeGen();while (timestamp <= lastTimestamp) {timestamp = timeGen();}return timestamp;}/*** 返回以毫秒为单位的当前时间* @return 当前时间(毫秒)*/protected long timeGen() {return System.currentTimeMillis();}//==============================Test=============================================/** 测试 */public static void main(String[] args) {SnowflakeIdWorker idWorker = new SnowflakeIdWorker(0, 0);for(int i= 0;i<10;i++) {long id = idWorker.nextId();System.out.println("id:" + id);}//id:768842202204864512}
}
Snowflake算法的优点是效率高,生成的ID具有有序性,适合分布式系统使用。
方式四:使用数据库自增主键
在关系型数据库中,自增主键是一种简单且常用的唯一ID生成方式。通过在数据库表中设置自增字段,每次插入新记录时,数据库会自动生成一个新的唯一ID。
CREATE TABLE users (id INT AUTO_INCREMENT PRIMARY KEY,username VARCHAR(50),email VARCHAR(100)
);
数据库自增主键的优点是实现简单,但缺点是依赖于数据库,不适合分布式系统。
方式五:使用Redis自增键
Redis是一个高性能的键值存储系统,它提供了自增键(INCR)命令,可以用来生成唯一的整数ID。
import redis.clients.jedis.Jedis;public class RedisIdGenerator {private Jedis jedis;public RedisIdGenerator() {jedis = new Jedis("localhost", 6379);}public long generateId() {return jedis.incr("id_counter");}
}
Redis自增键的优点是简单易用,适合需要高并发处理的场景。
方式六:使用Apache Commons Lang的IdGen
Apache Commons Lang是一个Java库,其中包含了一个名为IdGen
的工具类,可以用来生成唯一ID。
import org.apache.commons.lang3.math.NumberUtils;public class IdGen {public static void main(String[] args) {String uniqueId = IdGen.generateUniqueId();System.out.println("Unique ID: " + uniqueId);}
}
Apache Commons Lang的IdGen
类提供了多种生成唯一ID的方法,包括UUID、Snowflake算法等。
总结
本文介绍了六种在Java中高效生成唯一ID的方法,包括UUID、自定义UUID、Snowflake算法、数据库自增主键、Redis自增键和Apache Commons Lang的IdGen。根据具体的应用场景和需求,可以选择合适的方法来生成唯一ID。