2015-04-29 17 views
6

Ho eseguito il seguente script (java) e mi ha dato il risultato strano. Qualcuno può aiutare a spiegare?Perché Objects.hash() restituisce valori diversi per lo stesso input?

import java.util.Objects; 
import org.apache.log4j.Logger; 

public class CacheTester { 

private static final Logger log = Logger.getLogger(CacheTester.class); 

    @Test 
    public void hashCodeTest() { 
     for (int i = 0; i < 50; i++) { 
      // if I remove the third parameter, it works fine 
      log.info(Objects.hash("getDemoCache", "1", new int[]{1, 2})); 
     } 
    } 
} 

Registro dei risultati (sono diversi gli uni dagli altri):

//... 
2015-04-29 17:43:20 INFO CacheTester:42 - 1431904540 
2015-04-29 17:43:20 INFO CacheTester:42 - 1859187447 
2015-04-29 17:43:20 INFO CacheTester:42 - -2146933580 
2015-04-29 17:43:20 INFO CacheTester:42 - -2074242201 
2015-04-29 17:43:20 INFO CacheTester:42 - 1363170000 
2015-04-29 17:43:20 INFO CacheTester:42 - 1040980265 
2015-04-29 17:43:20 INFO CacheTester:42 - 1639331053 
2015-04-29 17:43:20 INFO CacheTester:42 - 570765746 
2015-04-29 17:43:20 INFO CacheTester:42 - -2023288896 
2015-04-29 17:43:20 INFO CacheTester:42 - -1892732019 
2015-04-29 17:43:20 INFO CacheTester:42 - 1464306601 
2015-04-29 17:43:20 INFO CacheTester:42 - 921799986 
2015-04-29 17:43:20 INFO CacheTester:42 - 1037804977 
//... 

---- ---- Sfondo

ho voluto utilizzare il mio keyGenrator per l'annotazione @Cacheable (Primavera & ehCache).

public Object generate(Object target, Method method, Object... params) { 
    int key = Objects.hashCode(method.getName(), params); 
    log.info("key = " + key); 
    return key; 
} 

In questo caso, trovo che la cache manchi sempre.

poi devo cambiare a questo:

public Object generate(Object target, Method method, Object... params) { 
    int result = method.getName().hashCode() : 0; 
    result = 31 * result + Objects.hashCode(params); 
    return result; 
} 

Grazie

+2

'int []. HashCode()' è basato sull'identità, non sul contenuto. –

+0

Vedere http://stackoverflow.com/questions/744735/java-array-hashcode-implementation – ericbn

+0

Grazie a tutti. Imparo davvero molto! =) –

risposta

8

È perché hashCode per int[] sia di rango. Non c'è alcun motivo per cui due istanze di int[] devono avere lo stesso hashCode, anche se le voci sono uguali.

Prova questo:

System.out.println(new int[] {1, 2}.hashCode()); 
System.out.println(new int[] {1, 2}.hashCode()); 

Sarà quasi certamente vedere due interi diversi.

Un buon modo per utilizzare Objects.hash con gli array è quello di passare Arrays.hashCode(array) invece della matrice effettiva. Nel tuo caso potresti fare:

Objects.hash("getDemoCache", "1", Arrays.hashCode(new int[]{1, 2})) 
+1

Grazie, @pbabcdefp, mooolto! Mi hai salvato la vita. La tua spiegazione è molto chiara! –

+0

Aha! Grazie! Ho avuto un problema simile ma ho pensato che 'Stream.mapToInt()' avrebbe funzionato. Apparentemente restituisce un 'IntStream', quindi avevo bisogno di chiamare' stream.boxed(). ToArray() 'per convertire i miei interi in una lista di oggetti. Solo allora ho ricevuto codici hash coerenti. –

Problemi correlati