En la mayoría de las implementaciones de tipo hashcode(), las colisiones se aceptan como inevitables y se prueban.
Si absolutamente no debe haber colisiones, garantizado, la solución que perfilará funcionará.
Aparte de esto, hay funciones hash criptográficas como MD5 y SHA, donde las colisiones son extremadamente improbables (aunque con un gran esfuerzo puede forzarse). La arquitectura de criptografía Java tiene implementaciones de estos. Esos métodos tal vez sean más rápidos que una buena implementación de su solución para conjuntos muy grandes. También se ejecutarán en tiempo constante y darán el mismo código para la misma cadena, sin importar en qué orden se agreguen las cadenas. Además, no requiere almacenar cada cadena. Los resultados de hash Crypto se pueden considerar como enteros, pero no caben en un int java: se puede usar un BigInteger para mantenerlos como se sugiere en otra respuesta. Por cierto, si te molesta la idea de que una colisión sea "extremadamente improbable", es probable que haya una probabilidad similar de que un poco voltee aleatoriamente en la memoria de tu computadora o en tu disco duro y provoque que un programa se comporte de manera diferente a la tuya. espera :-)
Nota, también hay algunas debilidades teóricas en algunas funciones hash (por ejemplo, MD5) pero para sus propósitos probablemente no importe y podría usar la función más eficiente - esas debilidades son solo relevantes si alguien trata maliciosamente de encontrar cadenas que tengan el mismo código que otra cadena.
editar: Me acabo de dar cuenta en el título de su pregunta, parece que quiere un mapeo bidireccional, aunque en realidad no dice esto en la pregunta. No es posible (por diseño) pasar de un hash Crypto a la cadena original. Si realmente lo necesita, tendrá que almacenar un mapa que manipule los hashes nuevamente en cadenas.
No estoy seguro de por qué querría Entero mapas fácilmente a cadenas a toString() y viceversa con Integer.valueOf() Entonces, ¿cuál es el punto? – cletus
@cletus: "Hola" no se asigna fácilmente a un número entero utilizando Integer.valueOf(). –
¿La validez de las pruebas es parte del problema? Esta pregunta realmente necesita ser reformulada y/o aclarada. Realmente no tiene ningún sentido como es. – cletus