Como gerar uma string aleatória em Java sem enlouquecer?
\n\nImagine: você está criando um cadastro em um site. Precisa gerar um token único para confirmar o e-mail. Ou gerar uma senha para um novo usuário. Ou simplesmente criar um ID legível para um link. A primeira coisa que vem à mente é usar UUID.randomUUID(), remover os hífens e ficar feliz.
Pare. Você sabia que uma ação aparentemente simples pode se tornar um gargalo de desempenho? A pergunta no Stack Overflow "How to generate a random alpha-numeric string" acumulou milhares de visualizações por um motivo. O diabo, como sempre, está nos detalhes: a escolha do gerador de números aleatórios, o algoritmo, o gerenciamento de memória. Neste artigo, não vamos apenas escrever código — vamos otimizá-lo ao máximo.
\n\nPrepare o IntelliJ IDEA. Vamos nessa!
\n\n1. A maneira mais simples (mas lenta): UUID
\n\nVamos começar com o clássico. UUID gera um valor de 128 bits. Se removermos os hífens, obtemos 32 caracteres em formato hexadecimal (0-9, a-f). Isso já é uma string alfanumérica, mas com um alfabeto limitado.
public static String generateWithUUID() {\n return UUID.randomUUID().toString().replace("-", "");\n}\n\n\nPrós: Uma linha de código. Não precisa pensar.
\nContras: Não é possível controlar o comprimento. Apenas caracteres hexadecimais (16 caracteres do alfabeto). Para senhas, é fraco. Para tokens, serve, mas há uma ressalva.
\n\nA propósito, UUID.randomUUID() usa SecureRandom internamente. É criptograficamente seguro, mas lento. Se você precisa de 10.000 strings por segundo, este método vai decepcionar.
2. RandomStringUtils do Apache Commons Lang
\n\nUm clássico que migra de projeto em projeto. A biblioteca commons-lang3 oferece um método pronto:
import org.apache.commons.lang3.RandomStringUtils;\n\npublic static String generateWithCommons(int length) {\n return RandomStringUtils.randomAlphanumeric(length);\n}\n\n\nBonito? Sim. Performático? Nem tanto.
\nInternamente, RandomStringUtils usa java.util.Random (não criptograficamente seguro) e cria muitos objetos temporários. Para a maioria das tarefas, é suficiente, mas se você estiver gerando milhões de strings, prepare-se para pausas do GC.
3. Método personalizado com Random.nextInt()
\n\nVamos criar nossa própria solução. A maneira mais óbvia:
\n\nimport java.security.SecureRandom;\nimport java.util.Random;\n\npublic class RandomStringGenerator {\n private static final String ALPHANUMERIC = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";\n private static final int BASE = ALPHANUMERIC.length();\n private final Random random;\n\n public RandomStringGenerator() {\n this.random = new SecureRandom(); // para segurança criptográfica\n }\n\n public String generate(int length) {\n StringBuilder sb = new StringBuilder(length);\n for (int i = 0; i < length; i++) {\n sb.append(ALPHANUMERIC.charAt(random.nextInt(BASE)));\n }\n return sb.toString();\n }\n}\n\n\nO que é importante aqui?
\n- \n
- Usamos
StringBuildercom capacidade conhecida — sem expansões desnecessárias. \n SecureRandomgarante que a saída não pode ser prevista. Para tokens, é essencial. \n - O alfabeto é definido como uma string — 62 caracteres (26+26+10). É possível adicionar caracteres especiais. \n
Mas há um problema: SecureRandom pode ser lento no Linux (esperando por entropia). Se a velocidade for mais importante que a segurança, use ThreadLocalRandom.current().
4. Otimização com char[] e ThreadLocalRandom
\n\nQuer extrair o máximo? Abandone o StringBuilder e trabalhe diretamente com um array de caracteres:
import java.util.concurrent.ThreadLocalR