UUID 라이브러리는 32 자 UUID를 생성합니다.
8 자 전용 UUID를 생성하고 싶습니다. 가능합니까?
UUID 라이브러리는 32 자 UUID를 생성합니다.
8 자 전용 UUID를 생성하고 싶습니다. 가능합니까?
답변:
UUID는 정의당 16 바이트 숫자이므로 불가능합니다. 물론 8 자 길이의 고유 한 문자열을 생성 할 수 있습니다 (다른 답변 참조).
또한 ID의 일부가 고정 된 바이트를 포함 할 수 있으므로 더 긴 UUID를 생성하고 하위 문자열을 지정할 때주의해야합니다 (예 : MAC, DCE 및 MD5 UUID의 경우).
RandomStringUtils
apache.commons에서 수업을 시도 할 수 있습니다 .
import org.apache.commons.lang3.RandomStringUtils;
final int SHORT_ID_LENGTH = 8;
// all possible unicode characters
String shortId = RandomStringUtils.random(SHORT_ID_LENGTH);
URL이나 사람에게 친숙하지 않은 모든 가능한 문자가 포함된다는 점을 명심하십시오.
따라서 다른 방법도 확인하십시오.
// HEX: 0-9, a-f. For example: 6587fddb, c0f182c1
shortId = RandomStringUtils.random(8, "0123456789abcdef");
// a-z, A-Z. For example: eRkgbzeF, MFcWSksx
shortId = RandomStringUtils.randomAlphabetic(8);
// 0-9. For example: 76091014, 03771122
shortId = RandomStringUtils.randomNumeric(8);
// a-z, A-Z, 0-9. For example: WRMcpIk7, s57JwCVA
shortId = RandomStringUtils.randomAlphanumeric(8);
다른 사람들이 말했듯이 더 작은 id와 id 충돌 가능성이 중요 할 수 있습니다. 생일 문제 가 귀하의 경우에 어떻게 적용 되는지 확인하십시오 . 이 답변 에서 근사치를 계산하는 방법에 대한 좋은 설명을 찾을 수 있습니다 .
org.apache.commons.lang3.RandomStringUtils
사용되지 않습니다, 당신은 사용 좋을 것 org.apache.commons.text.RandomStringGenerator
에 commons.apache.org/proper/commons-text
RandomStringGenerator
코드가 완전히 다르기 때문에에 대한 새로운 답변을 추가했습니다 .
RandomStringUtils
더 이상 사용되지 않습니다. 간단한 사용을위한 것입니다. RandomStringUtils
더 이상 사용되지 않는 정보의 소스를 제공 할 수 있습니까 ? RandomStringUtils
더 이상 사용되지 않는다는 증거로 의 최신 버전 문서를 제공 할 수 있습니다 . commons.apache.org/proper/commons-lang/javadocs/api-3.9/org/…
첫째 : java UUID.randomUUID 또는 .net GUID에서 생성 된 고유 ID조차도 100 % 고유하지 않습니다. 특히 UUID.randomUUID는 128 비트 (보안) 임의 값 "전용"입니다. 따라서 64 비트, 32 비트, 16 비트 (또는 1 비트)로 줄이면 단순히 덜 고유 해집니다.
따라서 최소한 위험 기반 결정, uuid가 얼마나 길어야 하는가입니다.
둘째 : "8 자만"이라는 말은 일반 인쇄 가능한 8 자 문자열을 의미한다고 가정합니다.
길이가 8 개의 인쇄 가능한 문자로 된 고유 한 문자열을 원한다면 base64 인코딩을 사용할 수 있습니다. 이것은 문자 당 6 비트를 의미하므로 총 48 비트를 얻게됩니다 (매우 고유하지는 않지만 응용 프로그램에 적합 할 수도 있음).
따라서 방법은 간단합니다. 6 바이트 임의 배열 생성
SecureRandom rand;
// ...
byte[] randomBytes = new byte[16];
rand.nextBytes(randomBytes);
그런 다음 예를 들어 다음과 같이 Base64 문자열로 변환합니다. org.apache.commons.codec.binary.Base64
BTW : 무작위로 "uuid"를 만드는 더 좋은 방법이 있는지 응용 프로그램에 따라 다릅니다. (초당 한 번만 UUID를 생성하는 경우 타임 스탬프를 추가하는 것이 좋습니다.) (참고 : 두 개의 임의 값을 결합 (xor)하면 결과는 항상 가장 임의의 값만큼 무작위로 나타납니다. 둘 다 무작위).
@Cephalopod가 말했듯이 불가능하지만 UUID를 22 자로 줄일 수 있습니다.
public static String encodeUUIDBase64(UUID uuid) {
ByteBuffer bb = ByteBuffer.wrap(new byte[16]);
bb.putLong(uuid.getMostSignificantBits());
bb.putLong(uuid.getLeastSignificantBits());
return StringUtils.trimTrailingCharacter(BaseEncoding.base64Url().encode(bb.array()), '=');
}
이것은 Anton Purin 답변을 기반으로 고유 한 오류 코드를 생성하기 위해 여기에서 사용하는 것과 비슷한 방법이지만 org.apache.commons.text.RandomStringGenerator
더 이상 사용되지 않는 (더 이상이 아닌) 대신 더 적절한 것에 의존합니다 org.apache.commons.lang3.RandomStringUtils
.
@Singleton
@Component
public class ErrorCodeGenerator implements Supplier<String> {
private RandomStringGenerator errorCodeGenerator;
public ErrorCodeGenerator() {
errorCodeGenerator = new RandomStringGenerator.Builder()
.withinRange('0', 'z')
.filteredBy(t -> t >= '0' && t <= '9', t -> t >= 'A' && t <= 'Z', t -> t >= 'a' && t <= 'z')
.build();
}
@Override
public String get() {
return errorCodeGenerator.generate(8);
}
}
충돌에 대한 모든 조언은 여전히 적용됩니다.
RandomStringUtils
더 이상 사용되지 않습니다. 간단한 사용을위한 것입니다. RandomStringUtils
더 이상 사용되지 않는 정보의 소스를 제공 할 수 있습니까 ? RandomStringUtils
더 이상 사용되지 않는다는 증거로 의 최신 버전 문서를 제공 할 수 있습니다 . commons.apache.org/proper/commons-lang/javadocs/api-3.9/org/…
commons.lang
어차피 언어 자체와 엄격하게 관련되지 않고 commons.text
목적을 가지고 만들어진 어떤 것도 사용해서는 안됩니다 .
RandomStringUtils
더 이상 사용되지 않으며 귀하가 제공 한 참조에 따르면 RandomStringGenerator
간단한 사용 사례 보다 사용하기가 훨씬 간단하기 때문에 더 이상 사용하지 않는 것이 좋습니다 . 답변을 업데이트 할 수 있습니까? RandomStringUtils
간단한 사용 사례에 대한 / 언제 또는 기능이로 이동되면 commons.text
답변을 다시 업데이트 할 수 있지만 현재는 오해의 소지가 있습니다.
commons.lang
으로 이동하고 있음이 분명합니다 commons.text
. 이미 다른 곳에서 사용하는 것 외에는 전자를 사용할 이유가 없습니다. 여기에서의 단순성은 다소 주관적입니다. 제 대답은 여전히 매우 간단하며 Commons Lang을 가져 오기 위해 필요한 것으로 변경하지 않았습니다.
이건 어때? 실제로이 코드는 최대 13자를 반환하지만 UUID보다 짧습니다.
import java.nio.ByteBuffer;
import java.util.UUID;
/**
* Generate short UUID (13 characters)
*
* @return short UUID
*/
public static String shortUUID() {
UUID uuid = UUID.randomUUID();
long l = ByteBuffer.wrap(uuid.toString().getBytes()).getLong();
return Long.toString(l, Character.MAX_RADIX);
}
getLong()
버퍼의 처음 8 바이트 만 읽는다는 것을 알고 있습니다. UUID에는 최소 36 바이트가 있습니다. 나에게 이것이 결코 작동하지 않기 때문에 나는 무언가를 놓치고 있는가?
실제로 타임 스탬프 기반의 더 짧은 고유 식별자를 원하므로 아래 프로그램을 시도했습니다.
nanosecond + ( endians.length * endians.length )
조합 으로 추측 할 수 있습니다.
public class TimStampShorterUUID {
private static final Character [] endians =
{'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j',
'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't',
'u', 'v', 'w', 'x', 'y', 'z',
'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J',
'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T',
'U', 'V', 'W', 'X', 'Y', 'Z',
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9'
};
private static ThreadLocal<Character> threadLocal = new ThreadLocal<Character>();
private static AtomicLong iterator = new AtomicLong(-1);
public static String generateShorterTxnId() {
// Keep this as secure random when we want more secure, in distributed systems
int firstLetter = ThreadLocalRandom.current().nextInt(0, (endians.length));
//Sometimes your randomness and timestamp will be same value,
//when multiple threads are trying at the same nano second
//time hence to differentiate it, utilize the threads requesting
//for this value, the possible unique thread numbers == endians.length
Character secondLetter = threadLocal.get();
if (secondLetter == null) {
synchronized (threadLocal) {
if (secondLetter == null) {
threadLocal.set(endians[(int) (iterator.incrementAndGet() % endians.length)]);
}
}
secondLetter = threadLocal.get();
}
return "" + endians[firstLetter] + secondLetter + System.nanoTime();
}
public static void main(String[] args) {
Map<String, String> uniqueKeysTestMap = new ConcurrentHashMap<>();
Thread t1 = new Thread() {
@Override
public void run() {
while(true) {
String time = generateShorterTxnId();
String result = uniqueKeysTestMap.put(time, "");
if(result != null) {
System.out.println("failed! - " + time);
}
}
}
};
Thread t2 = new Thread() {
@Override
public void run() {
while(true) {
String time = generateShorterTxnId();
String result = uniqueKeysTestMap.put(time, "");
if(result != null) {
System.out.println("failed! - " + time);
}
}
}
};
Thread t3 = new Thread() {
@Override
public void run() {
while(true) {
String time = generateShorterTxnId();
String result = uniqueKeysTestMap.put(time, "");
if(result != null) {
System.out.println("failed! - " + time);
}
}
}
};
Thread t4 = new Thread() {
@Override
public void run() {
while(true) {
String time = generateShorterTxnId();
String result = uniqueKeysTestMap.put(time, "");
if(result != null) {
System.out.println("failed! - " + time);
}
}
}
};
Thread t5 = new Thread() {
@Override
public void run() {
while(true) {
String time = generateShorterTxnId();
String result = uniqueKeysTestMap.put(time, "");
if(result != null) {
System.out.println("failed! - " + time);
}
}
}
};
Thread t6 = new Thread() {
@Override
public void run() {
while(true) {
String time = generateShorterTxnId();
String result = uniqueKeysTestMap.put(time, "");
if(result != null) {
System.out.println("failed! - " + time);
}
}
}
};
Thread t7 = new Thread() {
@Override
public void run() {
while(true) {
String time = generateShorterTxnId();
String result = uniqueKeysTestMap.put(time, "");
if(result != null) {
System.out.println("failed! - " + time);
}
}
}
};
t1.start();
t2.start();
t3.start();
t4.start();
t5.start();
t6.start();
t7.start();
}
}
최신 정보 :이 코드는 단일 JVM에서 작동하지만 분산 JVM에 대해 생각해야하므로 DB가있는 솔루션과 DB가없는 솔루션을 생각하고 있습니다.
DB로
회사 이름 (짧은 이름 3 자) ---- Random_Number ---- 키 특정 redis COUNTER
(3 자) -------------------------- ---------------------- (2 자) ---------------- (11 자)
DB없이
IPADDRESS ---- THREAD_NUMBER ---- INCR_NUMBER ---- epoch milliseconds
(5 chars) ----------------- (2char) --------- -------------- (2 자) ----------------- (6 자)
코딩이 완료되면 업데이트됩니다.
UUID는 아니지만 이것은 나를 위해 작동합니다.
UUID.randomUUID().toString().replace("-","").substring(0,8)
나는 그것이 가능하다고 생각하지 않지만 좋은 해결 방법이 있습니다.
new Random(System.currentTimeMillis()).nextInt(99999999);
하면 최대 8 자 길이의 임의 ID가 생성됩니다.영숫자 ID 생성 :
char[] chars = "abcdefghijklmnopqrstuvwxyzABSDEFGHIJKLMNOPQRSTUVWXYZ1234567890".toCharArray();
Random r = new Random(System.currentTimeMillis());
char[] id = new char[8];
for (int i = 0; i < 8; i++) {
id[i] = chars[r.nextInt(chars.length)];
}
return new String(id);