2015-04-29 19 views
6

Uruchomiłem skrypt (java), który dał mi dziwny wynik. Czy ktoś może pomóc ci wyjaśnić?Dlaczego Objects.hash() zwraca różne wartości dla tego samego wejścia?

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})); 
     } 
    } 
} 

Log Wynik (są one różne od siebie):

//... 
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 
//... 

---- Tło ----

chciałem stosować własne keyGenrator dla @Cacheable adnotacji (Wiosna & ehCache).

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

W takim przypadku pamięć podręczna jest zawsze pomijana.

Wtedy muszę zmienić to:

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

Dziękuję

+2

'int []. HashCode()' jest oparte na tożsamości, a nie na treści. –

+0

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

+0

Dziękuję wszystkim. Naprawdę dużo się uczę! =) –

Odpowiedz

8

To dlatego hashCode dla int[] nie jest przesłonięta. Nie ma powodu, dla którego dwa wystąpienia int[] powinny mieć ten sam hashCode, nawet jeśli wpisy są takie same.

Spróbuj tego:

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

Będziesz prawie na pewno zobaczyć dwie różne liczby całkowite.

Dobrym sposobem na użycie Objects.hash z tablicami jest przekazanie Arrays.hashCode(array) zamiast rzeczywistej tablicy. W twoim przypadku możesz zrobić:

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

Dziękuję, @ ​​pbabcdefp, sooo dużo! Ratujesz moje życie. Twoje wyjaśnienie jest bardzo jasne! –

+0

Aha! Dzięki! Miałem podobny problem, ale pomyślałem, że 'Stream.mapToInt()' zadziałałby. Najwyraźniej zwraca 'IntStream', więc potrzebowałem wywołania' stream.boxed(). ToArray() 'w celu przekonwertowania moich liczb całkowitych na listę obiektów. Dopiero wtedy otrzymałem spójne kody skrótów. –

Powiązane problemy