¿Por qué Java utiliza una implementación mediocre de hashCode para cadenas?

Refiriéndose a la documentación del hashCode de Object:

“Este método es compatible en beneficio de tablas hash como las proporcionadas por java.util.Hashtable”.

http://grepcode.com/file/reposit……

Los diseñadores del lenguaje Java agregaron hashcode principalmente para colecciones basadas en hash como HashTable y HashMap. La cadena no es diferente.

Si observa HashMap, notará que se utiliza “bit a bit” para asignar objetos a los depósitos de HashMap; esencialmente, los bits de orden inferior determinan el índice del depósito.

/ *** Devuelve el índice para el código hash h. * /
static int indexFor (int h, int length) {
retorno h & (longitud-1);
}

De tus días de escuela, puedes recordar haber usado
myString.hashCode() % numOfBuckets
para asignar un objeto a un cubo.

En Java HashMap (a partir de 1.4, creo), Josh Bloch et al cambiaron esto a myString.hashCode() & (numOfBuckets -1)

Esto es mucho más barato en términos de CPU, ya que el módulo (división) es más costoso que bit-AND o bit-shifts.

Siempre que los bits de orden inferior de myString.hashCode () sean aleatorios, este algoritmo obtendrá una distribución uniforme de objeto a cubo.

Sin embargo, dado que cualquiera puede anular el código hash para un objeto, Josh et al deben proporcionar algunas garantías. Esto se logra mediante un método hash complementario (en la clase HashMap).

/ *** Aplica una función hash complementaria a un código hash dado, que * defiende contra las funciones hash de baja calidad. Esto es crítico * porque HashMap usa tablas hash de potencia de dos longitudes, que * de lo contrario encuentran colisiones para códigos hash que no difieren * en bits más bajos. Nota: las teclas nulas siempre se asignan al hash 0, por lo tanto, el índice 0. * /

hash int estático (int h) {

// Esta función asegura que los códigos hash que difieren solo por
// los múltiplos constantes en cada posición de bit tienen un límite
// número de colisiones (aproximadamente 8 con el factor de carga predeterminado).

h ^ = (h >>> 20) ^ (h >>> 12); devuelve h ^ (h >>> 7) ^ (h >>> 4);
}

Para resumir, un objetivo clave del código hash de Java era admitir colecciones basadas en hash. Las colecciones basadas en hash como HashMap tratan algunos sesgos de bits y problemas relacionados con implementaciones de funciones hash pobres, por lo que una implementación mediocre de hashCode en String no es un gran problema.

El algoritmo de código hash se especifica en la documentación de String para que “no se les permita” cambiarlo (se rompería la compatibilidad con versiones anteriores). Algunas personas pueden tener programas escritos que dependen de este algoritmo específico

  • Porque es barato; Si necesita algo más sofisticado, probablemente tampoco podrá utilizar ninguna otra función predeterminada (que también debería ser barata). Hay una razón por la cual hashCode() es fácilmente reemplazable.
  • Incluso si es tentador, cambiarlo rompería cualquier aplicación con hashes almacenados.

Compatibilidad en su mayoría. Fue mucho peor en JDK 1.0 y 1.1, donde solo muestrearía cualquier otro personaje. JDK y superior multiplicaron un primo impar (31) por la secuencia char para evitar colisiones. Parece una compensación decente entre la velocidad y la reducción de colisiones.

More Interesting

¿Cómo puedes visualizar algoritmos?

Cómo determinar todas las condiciones, suposiciones y limitaciones para un código C # dado que calcula el valor promedio de una matriz de diferentes números

¿Por qué las listas enlazadas son más convenientes que las matrices en el dominio de la computación simbólica?

¿Cuál es una versión más amigable para principiantes de CLRS para algoritmos de aprendizaje? ¿Estaría rompiendo la entrevista de codificación?

¿Cuál es el algoritmo de cifrado más complejo?

¿Cuál es el algoritmo de clasificación más rápido con la menor complejidad?

Cómo entender el análisis amortizado y por qué lo necesitamos

¿Cuáles son ejemplos de la secuencia de Fibonacci en el campo de la ciencia y las artes liberales (economía, sociología, incluso historia, etc.)?

¿Existe un algoritmo que pueda combinar y separar números?

¿Qué haces si la resolución de un problema de algoritmo lleva demasiado tiempo?

¿Debería centrarme en el aprendizaje de algoritmos y estructuras de datos en profundidad, o aprender una habilidad como desarrollo web o desarrollo móvil usando Nanodegree?

Si tiene un trabajo diario bastante intenso, ¿cómo encuentra tiempo para mejorar la estructura de datos y la habilidad de los algoritmos?

Si recientemente completé un campo de entrenamiento y todo lo que queda para conseguir un trabajo es la prueba técnica, ¿cuántas horas serán suficientes los algoritmos de aprendizaje?

Cómo ordenar una lista anidada en Python

¿Qué es Algoritmo, Diagrama de flujo y Pseudocódigo en la planificación de programas antes de escribir?