If you need a plainly simple list of unique IDs at one point in time, you can use the following method:
package example;
import java.util.List;
import java.util.concurrent.ThreadLocalRandom;
import java.util.stream.Collectors;
public class Main {
public static void main(String[] args) {
final String prefix = "20210609";// hardcoded prefix for the example
final List<String> uniqueIds = ThreadLocalRandom.current().ints(0, 10_000)// ints from 0 to 10000 (exclusive) -> every possible 4 digit number
.distinct()// only distinct numbers
.limit(1000L)// exactly 1000 (up to 10000 possible)
.mapToObj(v -> String.format("%04d", v))// always 4 digits (format as string, lpad with 0s
.map(v -> prefix + v)// add our prefix
.collect(Collectors.toList());
System.out.println(uniqueIds);
}
}
If you need a component that provides you with one unique ID at a time, you can use this class:
package example;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.concurrent.ThreadLocalRandom;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;
public class IdGenerator {
private static final int LENGTH = 10_000;
private static final DateTimeFormatter DTF = DateTimeFormatter.ofPattern("yyMMdd");// unlike SimpleDateFormat, this is thread-safe
private final Object monitor;
private final AtomicInteger offset;
private final AtomicBoolean generationInProgress;
private volatile int[] ids;
private volatile LocalDate lastGeneratedDate;
public IdGenerator() {
this.monitor = new Object();
this.offset = new AtomicInteger(0);
this.generationInProgress = new AtomicBoolean(false);
this.ids = new int[LENGTH];
this.lastGeneratedDate = LocalDate.MIN;
}
public String nextId() throws InterruptedException {
final LocalDate currentDate = LocalDate.now();
while (this.lastGeneratedDate.isBefore(currentDate)) {
if (this.generationInProgress.compareAndSet(false, true)) {
this.ids = ThreadLocalRandom.current().ints(0, LENGTH)
.distinct()
.limit(LENGTH)
.toArray();
this.offset.set(0);
this.lastGeneratedDate = currentDate;
this.generationInProgress.set(false);
synchronized (this.monitor) {
this.monitor.notifyAll();
}
}
while (this.generationInProgress.get()) {
synchronized (this.monitor) {
this.monitor.wait();
}
}
}
final int myIndex = this.offset.getAndIncrement();
if (myIndex >= this.ids.length) {
throw new IllegalStateException("no more ids today");
}
return currentDate.format(DTF) + String.format("%04d", this.ids[myIndex]);
}
}
Note that your pattern allows only 10000 unique IDs per day. You limit yourself to 4 digits per day (10^4 = 10000
).