これをチェックして、
List<String> list = new ArrayList<String>();
for (int i = 0; i < 10000; i++) {
String value = (""+UUID.randomUUID().getLeastSignificantBits()).substring(3, 20);
assertFalse(list.contains(value));
assertTrue(value.length() < 18);
list.add(value);
}
このメソッドは魅力のように通過します。また、最上位ビットよりも最下位ビットを取得する方がわずかに優れているという印象があります。最上位ビットでは、一部の情報に対して6ビットが固定されており、最下位ビットではそうではないためです。したがって、平均して、最上位ビットと衝突するには 2^29 個の UUID を生成する必要がありますが、最下位ビットとは 2^32 個の衝突が発生します。参照: SO スレッド。私はそれを仮定するのは正しいですか?
ここで、メソッドから取得した最下位ビットの最上位 2 桁を切り刻んでいます。私はそれに部分文字列を使用しています。2桁と符号ビットを切り落としていることに注意してください。これは、衝突を起こすために平均して 2^31 個の UUID を生成する必要があるということではないでしょうか?
正確には、17 桁を超えてはならない一意の識別子を生成しようとしています。Java 型という意味ではなく、整数でなければなりません。私のアプローチはどれくらい信頼できますか?
メタ情報:
実際、私たちはいくつかのレガシー システムと統合しており、17 桁以下の一意の番号を提供する必要があります。彼らはそれをデータベースの一意のキーとして持っていると思います。この場合、シーケンスを使用することもできます。最初にそれを提案しました。しかし、代わりに乱数を考え出すことができれば良いと彼らは私に言ったので、消費者は推測できません.
Java での UUID のタイプ 4 実装に関して私が知る限り、衝突を起こすには平均で 2^61 個の UUID を生成する必要があります。これは、最下位ビットで衝突を取得するには 2^32 を生成し、最上位ビットで衝突を取得するには 2^29 を生成する必要があることを意味するのではないでしょうか? はいの場合、左端の 2 桁を切り刻んだ後、最下位ビットの衝突を得るために平均 2^31 を生成する必要があると仮定するのは正しくありませんか?
私も使用しようとしましSecureRandom
たが、それも19桁の長い値を与えています。したがって、私も最初にその数字に切り刻むことになります。以下はそのためのコードです。
List<String> list = new ArrayList();
Random random = new SecureRandom();
for (int i = 0; i < 10000; i++) {
String value = ""+random.nextLong().substring(2, 19);
assertFalse(list.contains(value));
assertTrue(value.length() < 18);
list.add(value);
}
私が考えることができる他のオプションは、「yyMMddHHmmssSSS
+2-seq-digits」形式で日付を使用することです。しかし、それはプロセッサに大きく依存し、推測可能であると思います。99 ラウンド後にミリ秒単位で変化があったかどうかはよくわからないからです。私はそうするかもしれませんが、それはプロセッサの速度に依存します。ただし、99 の同時リクエストはほとんどありません。