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.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.