2012-05-14 15 views
8

¿Cuál puede ser el más rápido y más robusto (en términos de singularidad) camino para la implementación de un método comoCreación de un hash de varios cadena de objetos Java

public abstract String hash(String[] values); 

La matriz values[] tiene de 100 a 1.000 miembros, cada uno de una que con pocas docenas de caracteres, y el método debe ejecutarse aproximadamente 10,000 veces/seg en una matriz values[] diferente cada vez.

¿Debe construirse una cadena larga utilizando un buffer StringBuilder y luego un método hash invocado en el contenido del buffer, o es mejor seguir invocando el método hash para cada cadena de values[]?

Obviamente se necesita un hash de al menos 64 bits (por ejemplo, MD5) para evitar colisiones, pero ¿hay algo más simple y rápido que se pueda hacer con la misma calidad?

Por ejemplo, ¿qué pasa con

public String hash(String[] values) 
{ 
    long result = 0; 

    for (String v:values) 
    { 
     result += v.hashCode(); 
    } 

    return String.valueOf(result); 
} 
+1

Ese enfoque parece razonable.Es posible que desee almacenar el valor hash en un campo para que no tenga que volver a calcularlo cada vez, siempre y cuando lo actualice cada vez que su String [] cambie. –

+0

Claro, pero en la aplicación en cuestión la matriz values ​​[] cambia todo el tiempo. :-) – PNS

Respuesta

9

Definitivamente no utilizan Además normal debido a sus propiedades de linealidad, pero puede modificar su código sólo un poco para lograr la muy buena dispersión.

public String hash(String[] values) { 
    long result = 17; 
    for (String v:values) result = 37*result + v.hashCode(); 
    return String.valueOf(result); 
} 
+0

¿Tiene 17 años o se necesitaría una prima más larga? ¿Y qué hay de las colisiones en decenas de millones de invocaciones? – PNS

+0

Las colisiones son inevitables, sin embargo, la enciende. Si es una preocupación, debe usar algo más fuerte y con más de 64 bits. –

1

En primer lugar, el código hash es típicamente numérico, p. Ej. int. Además, su versión de la función hash crea int y luego hace que su cadena de representación en mi humilde opinión no tenga ningún sentido.

Me mejorar su método de hash de la siguiente manera:

public int hash(String[] values) { 
    long result = 0; 
    for (String v:values) { 
     result = result * 31 + v.hashCode(); 
    } 
    return result; 
} 

echar un vistazo en hashCode() implementado en la clase java.lang.String

+0

Acepto, pero el tipo de devolución es una formalidad de la solicitud. Aparte de eso, tu sugerencia es similar a la de Marko. ¿Estaría bien con respecto a las colisiones entre decenas de millones de invocaciones? – PNS

+0

@MarkoTopolnik ¿Por qué es eso un problema? – augurar

2

Usted debe mirar hacia fuera para crear debilidades cuando la combinación de métodos. (La función de hash de Java y la tuya). Hice una pequeña investigación sobre cifrados en cascada, y este es un ejemplo de ello. (La adición podría interferir con el funcionamiento interno de hashCode()

Los detalles internos de hashCode() se ven así:.

 for (int i = 0; i < len; i++) { 
      h = 31*h + val[off++]; 
     } 

números para sumar causarán los últimos caracteres de todas las cadenas de la matriz de solo se debe agregar, lo que no reduce la aleatoriedad (esto ya es suficientemente malo para una función hash).

Si desea pseudoaleabilidad real, eche un vistazo al algoritmo hash FNV. Es el algoritmo hash más rápido que existe que está especialmente diseñado para su uso en HashMaps.

dice así:

long hash = 0xCBF29CE484222325L; 
    for(String s : strings) 
    { 
     hash ^= s.hashCode(); 
     hash *= 0x100000001B3L; 
    } 

^Esta no es la aplicación real de la FNV, ya que toma como entrada enteros en lugar de bytes, pero creo que funciona igual de bien.

+0

Hmmm ... ¿Estás seguro de que esto es más rápido que los otros enfoques simples sugeridos aquí? La aleatoriedad es probablemente mejor, por lo que parece. – PNS

+0

Nunca dije que sea más rápido que cualquier otra cosa. De hecho, la velocidad es idéntica a las otras respuestas. (suponiendo que la suma y xor son iguales en términos de velocidad) –

+0

"aleatoriedad real" - nada del tipo que se encuentra aquí. – Raphael

3

No proporciona un hash de 64 bits, pero dado el título de la pregunta, probablemente valga la pena mencionar que desde Java 1.7 hay java.util.Objects#hash(Object...).

Cuestiones relacionadas