web-dev-qa-db-ja.com

Java(UUID.randomUUID()。toString()にダッシュなしでUUID文字列を生成する効率的な方法)

ユニークなバイトシーケンスを生成する効率的なユーティリティが欲しいです。 UUIDは適切な候補ですが、UUID.randomUUID().toString()44e128a5-ac7a-4c9a-be4c-224b6bf81b20のようなものを生成します。これは、HTTPで送信する必要がない限り有効です。この場合、ダッシュを削除する必要があります。

私は英数字からのみランダムな文字列を生成する効率的な方法を探しています(ダッシュやその他の特別な記号はありません)。

118
Maxim Veksler

UUID.Java実装に基づいて独自の何かを書くことになりました。 IDを生成しないであることに注意してください。代わりに、考えられる最も効率的な方法で、ランダムな32バイトの16進数文字列になります。

実装

import Java.security.SecureRandom;
import Java.util.UUID;

public class RandomUtil {
    // Maxim: Copied from UUID implementation :)
    private static volatile SecureRandom numberGenerator = null;
    private static final long MSB = 0x8000000000000000L;

    public static String unique() {
        SecureRandom ng = numberGenerator;
        if (ng == null) {
            numberGenerator = ng = new SecureRandom();
        }

        return Long.toHexString(MSB | ng.nextLong()) + Long.toHexString(MSB | ng.nextLong());
    }       
}

使用法

RandomUtil.unique()

テスト

動作を確認するためにテストした入力の一部:

public static void main(String[] args) {
    System.out.println(UUID.randomUUID().toString());
    System.out.println(RandomUtil.unique());

    System.out.println();
    System.out.println(Long.toHexString(0x8000000000000000L |21));
    System.out.println(Long.toBinaryString(0x8000000000000000L |21));
    System.out.println(Long.toHexString(Long.MAX_VALUE + 1));
}
10
Maxim Veksler

これはそれを行います:

public static void main(String[] args) {
    final String uuid = UUID.randomUUID().toString().replace("-", "");
    System.out.println("uuid = " + uuid);
}
221
Steve McLeod

このスレッドのURLを見るとわかるように、ダッシュをHTTPリクエストから削除する必要はありません。ただし、データに依存せずに整形式のURLを準備する場合は、データの標準形式を変更する代わりにURLEncoder.encode(String data、String encoding)を使用する必要があります。 UUID文字列表現の場合、ダッシュは正常です。

28
Donz

JUG(Java UUID Generator)を使用して一意のIDを生成しました。 JVM全体で一意です。かなり使いやすい。参照用のコードは次のとおりです。

private static final SecureRandom secureRandom = new SecureRandom();
private static final UUIDGenerator generator = UUIDGenerator.getInstance();

public synchronized static String generateUniqueId() {
  UUID uuid = generator.generateRandomBasedUUID(secureRandom);

  return uuid.toString().replaceAll("-", "").toUpperCase();
}

ライブラリは次の場所からダウンロードできます。 https://github.com/cowtowncoder/Java-uuid-generator

10
Sheng Chien

非常に多くの文字列がUUIDのアイデアに取って代わるのを見て驚いています。これはどう:

UUID temp = UUID.randomUUID();
String uuidString = Long.toHexString(temp.getMostSignificantBits())
     + Long.toHexString(temp.getLeastSignificantBits());

これは、UUIDのtoString()全体が、解析および実行する必要のある正規表現、または空の文字列で置換することは言うまでもなく、すでにより高価であるため、これを行う高速な方法です。

7
Stephan

簡単な解決策は

UUID.randomUUID().toString().replace("-", "")

(既存のソリューションのように、 String#replaceAll 呼び出しを回避するだけです。ここでは正規表現の置換は必要ないため、技術的にはまだですが String#replace がより自然に感じられます正規表現を使用して実装されます。UUIDの生成は置換よりもコストがかかるため、ランタイムに大きな違いはありません。

UUIDクラスの使用はおそらくほとんどのシナリオで十分に高速ですが、後処理を必要としない特殊な手書きのバリアントはより高速になると予想されます。とにかく、全体的な計算のボトルネックは通常、乱数ジェネレーターになります。 UUIDクラスの場合、 SecureRandom を使用します。

使用する乱数ジェネレーターは、アプリケーションに依存するトレードオフでもあります。セキュリティが重要な場合は、一般にSecureRandomが推奨されます。それ以外の場合、 ThreadLocalRandom が代替です(SecureRandomまたは古い Random よりも高速ですが、暗号的に安全ではありません)。

3
Philipp Claßen

UUIDのtoString()メソッドをコピーし、更新して「-」を削除しました。他のソリューションよりもはるかに高速で簡単です

public String generateUUIDString(UUID uuid) {
    return (digits(uuid.getMostSignificantBits() >> 32, 8) +
            digits(uuid.getMostSignificantBits() >> 16, 4) +
            digits(uuid.getMostSignificantBits(), 4) +
            digits(uuid.getLeastSignificantBits() >> 48, 4) +
            digits(uuid.getLeastSignificantBits(), 12));
}

/** Returns val represented by the specified number of hex digits. */
private String digits(long val, int digits) {
    long hi = 1L << (digits * 4);
    return Long.toHexString(hi | (val & (hi - 1))).substring(1);
}

使用法:

generateUUIDString(UUID.randomUUID())

リフレクションを使用した別の実装

public String generateString(UUID uuid) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {

    if (uuid == null) {
        return "";
    }

    Method digits = UUID.class.getDeclaredMethod("digits", long.class, int.class);
    digits.setAccessible(true);

    return ( (String) digits.invoke(uuid, uuid.getMostSignificantBits() >> 32, 8) +
            digits.invoke(uuid, uuid.getMostSignificantBits() >> 16, 4) +
            digits.invoke(uuid, uuid.getMostSignificantBits(), 4) +
            digits.invoke(uuid, uuid.getLeastSignificantBits() >> 48, 4) +
            digits.invoke(uuid, uuid.getLeastSignificantBits(), 12));

}
1
Ravi Desai

Org.Apache.commons.codec.binary.Base64を使用して、UUIDを22文字の長さでUUIDと同じ一意性を持つURLセーフな一意の文字列に変換します。

base64文字列としてUUIDを保存 にコードを投稿しました

0
stikkos