Эффективный метод для генерации строки UUID в JAVA (UUID.randomUUID (). ToString () без черточек) - PullRequest
124 голосов
/ 27 сентября 2010

Мне нужна эффективная утилита для генерации уникальных последовательностей байтов.UUID - хороший кандидат, но UUID.randomUUID().toString() генерирует такие вещи, как 44e128a5-ac7a-4c9a-be4c-224b6bf81b20, что хорошо, если вам не нужно передавать его по HTTP, и в этом случае необходимо удалить тире.Я ищу эффективный способ генерирования случайных строк, только из буквенно-цифровых символов (без тире или любых других специальных символов).

Ответы [ 8 ]

224 голосов
/ 27 сентября 2010

Это делает это:

public static void main(String[] args) {
    final String uuid = UUID.randomUUID().toString().replace("-", "");
    System.out.println("uuid = " + uuid);
}
28 голосов
/ 27 сентября 2010

Тире не нужно удалять из HTTP-запроса, как вы можете видеть в URL этой темы. Но если вы хотите подготовить правильно сформированный URL без зависимости от данных, вы должны использовать URLEncoder.encode (String data, String encoding) вместо изменения стандартной формы ваших данных. Для строкового представления UUID штрихи нормальны.

11 голосов
/ 28 сентября 2010

Я использовал JUG (Java UUID Generator) для генерации уникального идентификатора. Это уникально среди 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 голосов
/ 28 сентября 2010

Закончил писать что-то свое на основе реализации UUID.java. Обратите внимание, что я не генерирую UUID , а просто случайную шестнадцатеричную 32-байтовую строку наиболее эффективным способом, который я мог себе представить.

Осуществление

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));
}
7 голосов
/ 23 июня 2016

Я поражен, увидев, что так много строк заменяет идеи UUID. Как насчет этого:

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

Это быстрый способ сделать это, поскольку весь метод toString () UUID уже стоит дороже, не говоря уже о регулярном выражении, которое необходимо проанализировать и выполнить, или о замене пустой строкой.

3 голосов
/ 08 сентября 2016

Простое решение -

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

(Как и существующие решения, только то, что он избегает вызова String # replaceAll . Замена регулярного выражения здесь не требуется, поэтому String # replace выглядит более естественным, хотя технически все еще реализуется с помощью регулярных выражений. Учитывая, что генерация UUID обходится дороже, чем замена, не должно быть значительной разницы во времени выполнения.)

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

Какой генератор случайных чисел использовать, также является компромиссом, который зависит от приложения. Если это чувствительно к безопасности, SecureRandom, как правило, является рекомендацией. В противном случае ThreadLocalRandom является альтернативой (быстрее, чем SecureRandom или старый Случайный , но не криптографически защищен).

1 голос
/ 10 мая 2018

Я только что скопировал метод toString () UUID и просто обновил его, чтобы удалить из него "-". Это будет намного быстрее и понятнее, чем любое другое решение

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));

}
0 голосов
/ 08 августа 2013

Я использую org.apache.commons.codec.binary.Base64, чтобы преобразовать UUID в уникальную строку, безопасную для URL, длиной 22 символа и обладающую той же уникальностью, что и UUID.

Я разместил свой код на Сохранение UUID как base64 String

...