Как создать удобные для пользователя уникальные идентификаторы, UUID или другие уникальные идентификаторы в Java - PullRequest
11 голосов
/ 12 января 2011

Я обычно использую класс UUID для генерации уникальных идентификаторов.Это прекрасно работает, если эти идентификаторы используются только техническими системами, им все равно, как долго они:

System.out.println(UUID.randomUUID().toString());

> 67849f28-c0af-46c7-8421-94f0642e5d4d

Есть ли хороший способ создания удобных уникальных идентификаторов (например, из tinyurl), которыенемного короче, чем UUID?Вариант использования: вы хотите отправлять идентификаторы по почте своим клиентам, которые, в свою очередь, посещают ваш сайт и вводят этот номер в форму, например идентификатор ваучера.

Я предполагаю, что идентификаторы UUID генерируются одинаково во всем диапазоне128-битный диапазон UUID.Так будет ли мудро использовать, например, только младшие 64 бита?

System.out.println(UUID.randomUUID().getLeastSignificantBits());

Любые отзывы приветствуются.

Ответы [ 6 ]

9 голосов
/ 12 января 2011

Я предполагаю, что UUID генерируются одинаково во всем диапазоне 128-битного диапазона UUID.

Во-первых, ваше предположение может быть неверным, в зависимости от типа UUID (1, 2, 3 или 4).Начиная с Java UUID docs :

Существуют различные варианты этих глобальных идентификаторов.Методы этого класса предназначены для манипулирования вариантом Лича-Зальца, хотя конструкторы позволяют создавать любой вариант UUID (описан ниже).

Схема UUID варианта 2 (Leach-Salz) такова:следующее: Наиболее значимый длинный состоит из следующих полей без знака:

0xFFFFFFFF00000000 time_low 
0x00000000FFFF0000 time_mid 
0x000000000000F000 version 
0x0000000000000FFF time_hi  

Наименее значимый длинный состоит из следующих полей без знака:

0xC000000000000000 variant 
0x3FFF000000000000 clock_seq 
0x0000FFFFFFFFFFFF node  

Поле варианта содержит значение, которое идентифицирует макет UUID.Описанная выше схема битов действительна только для UUID со значением варианта 2, которое указывает вариант Лича-Зальца.

Поле версии содержит значение, которое описывает тип этого UUID.Существует четыре различных основных типа UUID: на основе времени, безопасности DCE, на основе имени и случайно сгенерированных UUID.Эти типы имеют значения версии 1, 2, 3 и 4. соответственно.

Лучший способ сделать то, что вы делаете, - сгенерировать случайную строку с кодом, который выглядит примерно так ( source ):

public class RandomString {

          public static String randomstring(int lo, int hi){
                  int n = rand(lo, hi);
                  byte b[] = new byte[n];
                  for (int i = 0; i < n; i++)
                          b[i] = (byte)rand('a', 'z');
                  return new String(b, 0);
          }

          private static int rand(int lo, int hi){
                      java.util.Random rn = new java.util.Random();
                  int n = hi - lo + 1;
                  int i = rn.nextInt(n);
                  if (i < 0)
                          i = -i;
                  return lo + i;
          }

          public static String randomstring(){
                  return randomstring(5, 25);
          }

        /**
         * @param args
         */
        public static void main(String[] args) {
                System.out.println(randomstring());

        }

}

Если вы невероятно беспокоитесь о столкновениях или чем-то еще, я предлагаю вам base64 кодировать свой UUID, что должно уменьшить его размер.

Мораль истории: не полагайтесь на отдельные части UUID, так как они разработаны целостно.Если вам нужно полагаться на отдельные части UUID, обязательно ознакомьтесь с конкретным типом и реализацией UUID.

3 голосов
/ 12 января 2011

Вот еще один подход для создания удобных идентификаторов:
http://thedailywtf.com/Articles/The-Automated-Curse-Generator.aspx

(но вы должны пойти на фильтр плохих слов)

2 голосов
/ 01 июня 2013

Любой UUID / Guid - это просто 16 байт данных. Эти 16 байтов могут быть легко закодированы с использованием BASE64 (или BASE64url), а затем удалены все символы «=» в конце строки.

Это дает хорошую короткую строку, которая по-прежнему содержит те же данные, что и UUID / Guid. Другими словами, можно воссоздать UUID / Guid из этих данных, если это станет необходимым.

1 голос
/ 17 мая 2014

Вот способ сгенерировать удобный для URL 22-символьный UUID

public static String generateShortUuid() {
        UUID uuid = UUID.randomUUID();

        long lsb = uuid.getLeastSignificantBits();
        long msb = uuid.getMostSignificantBits();

        byte[] uuidBytes = ByteBuffer.allocate(16).putLong(msb).putLong(lsb).array();

        // Strip down the '==' at the end and make it url friendly   
        return Base64.encode(uuidBytes)
                    .substring(0, 22)
                    .replace("/", "_")
                    .replace("+", "-");
    }

. В вашем случае было бы лучше отследить счетчик зарегистрированных пользователей и для каждого значения сгенерироватьстроковый токен, подобный следующему:

public static String longToReverseBase62(long value /* must be positive! */) {

        final char[] LETTERS = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ".toCharArray();

        StringBuilder result = new StringBuilder(9);
        do {
            result.append(LETTERS[(int)(value % 62)]);
            value /= 62l;
        }
        while (value != 0);

        return result.toString();
    }

В целях безопасности было бы лучше, если бы вы делали значения непоследовательными, поэтому каждый раз, когда пользователь регистрируется, вы можете увеличивать значение, скажем, на 1024 (Это было бы хорошо для генерации uuids для 2 ^ 64/2 ^ 10 = 2 ^ 54 пользователей, что, безусловно, больше, чем вам когда-либо нужно:)

0 голосов
/ 19 июня 2013

Как насчет этого? На самом деле этот код возвращает максимум 13 символов (цифры и строчные буквы).

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);
}
0 голосов
/ 12 января 2011

Только для вас :):

private final static char[] idchars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789".toCharArray();
private static String createId(int len) {
    char[] id = new char[len];
    Random r = new Random(System.currentTimeMillis());
    for (int i = 0;  i < len;  i++) {
        id[i] = idchars[r.nextInt(idchars.length)];

    }
    return new String(id);
}
...