¿Por qué String.hashCode () en Java tiene muchos conflictos? [cerrado

¿Por qué String.hashcode () tiene tantos conflictos?

Estoy leyendo String.hashCode () en jdk1.6, a continuación se muestran los códigos

public int hashCode() {
    int h = hash;
    if (h == 0) {
        int off = offset;
        char val[] = value;
        int len = count;

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

Esto me parece bastante confuso porque tiene muchos conflictos; aunque no se requiere que sea único (aún podemos confiar en los iguales ()), pero menos conflictos significa un mejor rendimiento sin visitar las entradas en una lista vinculada.

Supongamos que tenemos dos caracteres, entonces siempre que podamos encontrar dos cadenas que coincidan debajo de la ecuación, tendremos el mismo código hash ()

a * 31 +b = c * 31 +d

Será fácil concluir que(a-c) * 31 = d-b tome un ejemplo fácil es hacer a-c = 1 y d-b = 31; así que escribí los siguientes códigos para una prueba simple

public void testHash() {
    System.out.println("A:" + (int)'A');
    System.out.println("B:" + (int)'B');
    System.out.println("a:" + (int)'a');

    System.out.println("Aa".hashCode() + "," + "BB".hashCode());
    System.out.println("Ba".hashCode() + "," + "CB".hashCode());
    System.out.println("Ca".hashCode() + "," + "DB".hashCode());
    System.out.println("Da".hashCode() + "," + "EB".hashCode());        
}

it imprimirá los siguientes resultados, lo que significa que todas las cadenas tienen el mismo código hash (), y es fácil hacerlo en un bucle.

A:65 
B:66
a:97
2112,2112
2143,2143
2174,2174
2205,2205

ncluso peor, supongamos que tenemos 4 caracteres en la cadena, de acuerdo con el algoritmo, supongamos que los primeros 2 caracteres producen a2, los 2dos caracteres producen b2; el código hash seguirá siendoa2 * 31^2 + b2 por lo tanto, con a2 y b2 iguales entre 2 cadenas, obtendremos más cadenas con el conflicto hashcode (). tales ejemplos son "AaAa", "BBBB" y así sucesivamente; entonces tendremos 6 caracteres, 8 caracteres ......

supongamos que la mayoría de las veces usamos caracteres en una tabla ascii en una cadena que se usará en un hashmap o hashtable, entonces el número primo elegido 31 aquí es definitivamente demasiado pequeño;

una solución fácil es usar un número primo más grande (afortunadamente, 257 es un número primo) que puede evitar este conflicto. por supuesto, elegir un número demasiado grande hará que el valor int devuelto se desborde si la cadena es muy larga, pero supongo que la mayoría de las veces la cadena utilizada como clave no es tan grande. por supuesto, aún podría devolver un valor largo para evitar esto.

below es mi versión modificada de betterhash () que puede resolver tales conflictos fácilmente ejecutando los códigos que imprimirá debajo de los valores, lo cual es efectivo para resolver este problema.

16802,17028
17059,17285
17316,17542
17573,17799

pero ¿por qué jdk no lo arregla? Gracias

@Test
public void testBetterhash() {
    System.out.println(betterHash("Aa") + "," + betterHash("BB"));      
    System.out.println(betterHash("Ba") + "," + betterHash("CB"));
    System.out.println(betterHash("Ca") + "," + betterHash("DB"));
    System.out.println(betterHash("Da") + "," + betterHash("EB"));
}

public static int betterHash(String s) {
    int h = 0;
    int len = s.length();

    for (int i = 0; i < len; i++) {
        h = 257*h + s.charAt(i);
    }
    return h;
}

Respuestas a la pregunta(8)

Su respuesta a la pregunta