El valor de hashCode de una cadena Java se calcula como ( String.hashCode () ):
s[0]*31^(n-1) + s[1]*31^(n-2) + ... + s[n-1]
¿Hay alguna circunstancia (por ejemplo, versión de JVM, proveedor, etc.) en la que la siguiente expresión se evaluará como falsa?
boolean expression = "This is a Java string".hashCode() == 586653468
Actualización n. ° 1: Si afirma que la respuesta es "sí, existen tales circunstancias", entonces dé un ejemplo concreto de cuándo "Esto es una cadena de Java" .hashCode ()! = 586653468. Intente ser tan específico / concreto como sea posible.
Actualización n. ° 2: Todos sabemos que confiar en los detalles de implementación de hashCode () es malo en general. Sin embargo, estoy hablando específicamente sobre String.hashCode (), así que mantenga la respuesta enfocada en String.hashCode (). Object.hashCode () es totalmente irrelevante en el contexto de esta pregunta.
Respuestas:
Puedo ver esa documentación desde Java 1.2.
Si bien es cierto que en general no debe confiar en que la implementación de un código hash siga siendo la misma, ahora es un comportamiento documentado, por
java.lang.String
lo que cambiarlo contaría como romper los contratos existentes.Siempre que sea posible, no debe confiar en que los códigos hash permanezcan igual en todas las versiones, etc., pero en mi opinión
java.lang.String
es un caso especial simplemente porque se ha especificado el algoritmo ... siempre y cuando esté dispuesto a abandonar la compatibilidad con las versiones anteriores Se especificó el algoritmo, por supuesto.fuente
Encontré algo sobre JDK 1.0 y 1.1 y> = 1.2:
Algo diferente, porque parece que necesitas un número: ¿qué tal si usas CRC32 o MD5 en lugar de hashcode y estás listo para comenzar? Sin discusiones ni preocupaciones en absoluto ...
fuente
No debe confiar en que un código hash sea igual a un valor específico. Solo que devolverá resultados consistentes dentro de la misma ejecución. Los documentos API dicen lo siguiente:
EDITAR Dado que el javadoc para String.hashCode () especifica cómo se calcula el código hash de String, cualquier violación de esto violaría la especificación de API pública.
fuente
Como se dijo anteriormente, en general no debe confiar en que el código hash de una clase permanezca igual. Tenga en cuenta que incluso las ejecuciones posteriores de la misma aplicación en la misma VM pueden producir valores hash diferentes. La función hash de AFAIK the Sun JVM calcula el mismo hash en cada ejecución, pero eso no está garantizado.
Tenga en cuenta que esto no es teórico. La función hash para java.lang.String se cambió en JDK1.2 (el hash anterior tenía problemas con cadenas jerárquicas como URL o nombres de archivo, ya que tendía a producir el mismo hash para cadenas que solo diferían al final).
java.lang.String es un caso especial, ya que el algoritmo de su hashCode () está (ahora) documentado, por lo que probablemente pueda confiar en eso. Todavía lo consideraría una mala práctica. Si necesita un algoritmo hash con propiedades especiales y documentadas, simplemente escriba uno :-).
fuente
Otra cuestión (!) De la que preocuparse es el posible cambio de implementación entre versiones tempranas / tardías de Java. No creo que los detalles de implementación estén establecidos, por lo que potencialmente una actualización a una futura versión de Java podría causar problemas.
La conclusión es que no confiaría en la implementación de
hashCode()
.Quizás pueda resaltar qué problema realmente está tratando de resolver utilizando este mecanismo, y eso resaltará un enfoque más adecuado.
fuente
switch
declaraciones sobre cadenas se compilan en código que se basa en un código hash fijo particular, los cambios enString
el algoritmo de código hash definitivamente romperían el código existente ...Solo para responder a su pregunta y no para continuar ninguna discusión. La implementación de Apache Harmony JDK parece usar un algoritmo diferente, al menos se ve totalmente diferente:
Sun JDK
Armonía Apache
No dudes en comprobarlo tú mismo ...
fuente
s[0]*31^(n-1) + s[1]*31^(n-2) + ... + s[n-1]
menos que me equivoque, esto se debe a que Android usa la implementación de Sun del objeto String sin cambios.Si le preocupan los cambios y posiblemente las máquinas virtuales incompatibles, simplemente copie la implementación de código hash existente en su propia clase de utilidad y úsela para generar sus códigos hash.
fuente
El código hash se calculará en función de los valores ASCII de los caracteres en la cadena.
Esta es la implementación en la clase de cadena es la siguiente
Las colisiones en el código hash son inevitables. Por ejemplo, las cadenas "Ea" y "FB" dan el mismo código hash que 2236
fuente