Эффективный метод генерации строки UUID в JAVA (UUID.randomUUID().toString () без тире)

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

Я ищу эффективный способ генерации случайных строк, только из алфавитно-цифровых символов (без дефисов или других специальных символов).

8 ответов


вот это:

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

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


я использовал JUG (Java UUID Generator) для создания уникального идентификатора. Он уникален для JVMs. Довольно хорошо использовать. Вот код для вашей справки:

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


закончил тем, что написал что-то свое, основанное на 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));
}

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

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

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


простое решение

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

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

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

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


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

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


Я только что скопировал метод 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));

}