Introducción: Magia que no es aleatoria
\n\nSi alguna vez te quedaste atascado en Stack Overflow buscando la respuesta a un error extraño, seguramente viste la pregunta que acumuló miles de visitas y acalorados debates: "Why does this code using random strings print 'hello world'?". Suena como un acertijo, ¿verdad? ¿Cómo pueden cadenas generadas aleatoriamente formar un saludo con sentido?
\n\nEn este artículo no solo resolveremos este fenómeno SEO (sí, es un excelente caso para la promoción en buscadores de contenido educativo), sino que lo convertiremos en una lección completa sobre Java. Aprenderás cómo funcionan los pools de cadenas, por qué hashCode() a veces da sorpresas, y qué mejores prácticas deberías implementar en 2025 para que tu código sea predecible y eficiente.
¿Listo? ¡Allá vamos!
\n\n1. Ese código: ¿qué está pasando?
\n\nRecordemos el ejemplo clásico que explotó en Stack Overflow. Imagina que tienes un método que genera cadenas aleatorias y verifica su igualdad:
\n\npublic class RandomStringTest {\n public static void main(String[] args) {\n String[] randomStrings = new String[1000];\n for (int i = 0; i < 1000; i++) {\n randomStrings[i] = generateRandomString();\n }\n \n for (String s : randomStrings) {\n if (s.equals("hello world")) {\n System.out.println("Found: " + s);\n }\n }\n }\n \n public static String generateRandomString() {\n // Alguna lógica extraña\n return new StringBuilder()\n .append((char) (Math.random() * 256))\n .append((char) (Math.random() * 256))\n // ... muchos caracteres\n .toString();\n }\n}\n\n\nA primera vista, la probabilidad de obtener "hello world" al azar es (1/256)^11, prácticamente cero. Pero el código imprime "hello world". ¿Cómo? La aleatoriedad no tiene nada que ver. El secreto está en el pool de cadenas (String pool) y las particularidades del hashing en Java.
\n\n2. La solución: String Pool y hashCode
\n\nEn Java, las cadenas son objetos inmutables. Cuando creas una cadena mediante un literal ("hello world"), esta se almacena en el String pool, un área de memoria especial. Si otra cadena hace referencia al mismo valor, la JVM no crea un nuevo objeto, sino que devuelve una referencia al existente.
Pero en nuestro ejemplo, las cadenas se generan aleatoriamente. ¿Cómo es que siguen siendo iguales? Respuesta: hashCode() sobreescrito. En algunas versiones de Java (especialmente anteriores a la 8), el algoritmo de hashing de cadenas era predecible y podía provocar colisiones si las cadenas tenían la misma longitud y composición de caracteres. Sin embargo, la verdadera magia ocurre cuando el String pool utiliza internamiento.
\n\nCuando llamas a s.equals("hello world"), la JVM puede optimizar la comparación si ambas cadenas están en el pool. Pero en nuestro caso, las cadenas son diferentes... ¿O no? En realidad, si observas la implementación de generateRandomString() en la pregunta original, había un truco: el método devolvía una cadena que siempre era "hello world" debido a un error en la lógica de generación.
Aquí tienes un ejemplo de esa "aleatoriedad":
\n\npublic static String generateRandomString() {\n Random random = new Random(42); // Semilla fija\n byte[] bytes = new byte[11];\n random.nextBytes(bytes);\n return new String(bytes);\n}\n\n\nSi la semilla es fija, la secuencia "aleatoria" es siempre la misma. ¿Y si la semilla se elige para generar "hello world"? ¡Esa es la respuesta al acertijo! El código no es aleatorio, es determinista.
\n\n