11

I ran the follow script(java), and it gave me the weird result. Does anyone can help to explain?

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 Result(they are different from each other):

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

---- Background ----

I wanted to used my own keyGenrator for @Cacheable annotation(Spring & ehCache).

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

In this case, I find the cache are always missed.

Then I have to change to this:

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

Thank you

3
  • 2
    int[].hashCode() is identity-based, not content-based. Commented Apr 29, 2015 at 21:59
  • See stackoverflow.com/questions/744735/… Commented Apr 29, 2015 at 22:02
  • Thank you, all. Really learn a lot! =) Commented Apr 29, 2015 at 22:10

1 Answer 1

12

It's because hashCode for int[] is not overridden. There is no reason why two instances of int[] should have the same hashCode, even if the entries are the same.

Try this:

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

You will almost certainly see two different integers.

A good way to use Objects.hash with arrays is to pass Arrays.hashCode(array) instead of the actual array. In your case you could do:

Objects.hash("getDemoCache", "1", Arrays.hashCode(new int[]{1, 2})) 
Sign up to request clarification or add additional context in comments.

2 Comments

Thank you, @pbabcdefp, sooo much! You save my life. Your explanation is very clear!
Aha! Thanks! I had a similar problem but I thought Stream.mapToInt() would've worked. Apparently it returns an IntStream, so I needed call stream.boxed().toArray() in order to convert my integers into a list of objects. Only then I received consistent hash codes.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.