用Java生成唯一的ID方法
在开发过程中,生成唯一的ID是一个非常常见的需求。在Java中,生成唯一ID的方法有很多。本文将介绍一些常见的方法,并提供相应的代码示例。
1. 使用UUID类UUID(Universally Unique Identifier)它是唯一识别信息的标准化128位值。Java提供UUID类,可以轻松生成UUID。
import java.util.UUID;public class UuidDemo { public static void main(String[] args) { UUID uuid = UUID.randomUUID(); String id = uuid.toString(); System.out.println("生成的UUID:" + id); }}
使用上述代码UUID.randomUUID()
该方法生成UUID,并将其转换为字符串形式。操作程序,输出类似于1b29ff5d-98cd-4a3e-8c47-04982043
唯一的ID。
UUID的优点是简单快捷,生成的ID长度固定。但由于它是基于随机数生成的,不适合作为数据库的主键或排序依据。
2. 使用Snowflake算法Snowflake算法是Twitter开源生成唯一ID的算法。其核心思想是将64位longID分为多个部分,分别表示时间戳和机器ID、数据中心ID和序列号。在实际应用中,我们可以根据需要调整各部分的位数。
以下是示例代码:
public class SnowflakeDemo { private final long startTime = 1624454400000L; // 起始时间戳(2021-06-24) private final long dataCenterIdBits = 5L; // ID位数的数据中心 private final long workerIdBits = 5L; // 机器ID位数 private final long sequenceBits = 12L; // 序列号位数 private final long maxDataCenterId = -1L ^ (-1L << dataCenterIdBits); private final long maxWorkerId = -1L ^ (-1L << workerIdBits); private final long workerIdShift = sequenceBits; private final long dataCenterIdShift = sequenceBits + workerIdBits; private final long timestampLeftShift = sequenceBits + workerIdBits + dataCenterIdBits; private long workerId; private long dataCenterId; private long sequence = 0L; private long lastTimestamp = -1L; public SnowflakeDemo(long dataCenterId, long workerId) { if (dataCenterId > maxDataCenterId || dataCenterId < 0) { throw new IllegalArgumentException("Data center ID can't be greater than " + maxDataCenterId + " or less than 0"); } if (workerId > maxWorkerId || workerId < 0) { throw new IllegalArgumentException("Worker ID can't be greater than " + maxWorkerId + " or less than 0"); } this.dataCenterId = dataCenterId; this.workerId = workerId; } public synchronized long nextId() { long timestamp = System.currentTimeMillis(); if (timestamp < lastTimestamp) { throw new RuntimeException("Clock moved backwards. Refusing to generate ID"); } if (timestamp == lastTimestamp) { sequence = (sequence + 1) & ((1 << sequenceBits) - 1); if (sequence == 0) { timestamp = tilNextMillis(lastTimestamp); } } else { sequence = 0L; } lastTimestamp = timestamp; return ((timestamp - startTime) << timestampLeftShift) | (dataCenterId << dataCenterIdShift) | (workerId << workerIdShift) | sequence; } private long tilNextMillis(long lastTimestamp) { long timestamp = System.currentTimeMillis(); while (timestamp <= lastTimestamp) { timestamp = System.currentTimeMillis(); } return timestamp; } public static void main(String[] args) { SnowflakeDemo snowflake = new SnowflakeDemo(1, 1); long id = snowflake.nextId(); System.out.println("生成的ID:" + id); }}
Snowflake算法实现了上述代码startTime
表示启动时间戳,dataCenterIdBits
、workerIdBits
和sequenceBits
表示每个部分的位数。构造函数中传入的位数dataCenterId
和workerId
数据中心ID和机器ID分别表示。nextId()
通过左移、或运算和运算生成下一个唯一的ID