Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why Objects.hash() returns different values for the same input?

Tags:

java

hashcode

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

like image 516
Salty Egg Avatar asked Apr 29 '15 21:04

Salty Egg


People also ask

What happens if hashCode () method always return same value?

If multiple objects return the same value from hashCode(), it means that they would be stored in the same bucket. If many objects are stored in the same bucket it means that on average it requires more comparison operations to look up a given object.

Can two equal objects have the different hash code?

1) If two objects are equal (i.e. the equals() method returns true), they must have the same hashcode. 2) If the hashCode() method is called multiple times on the same object, it must return the same result every time. 3) Two different objects can have the same hash code.

What happens when 2 objects are the same while inserting it into the HashMap?

Whenever two different objects have the same hash code, we call this a collision. A collision is nothing critical, it just means that there is more than one object in a single bucket, so a HashMap lookup has to look again to find the right object.

How you write hashCode What if it returns different hashCode for same object?

Whenever it(hashcode) is invoked on the same object more than once during an execution of a Java application, the hashCode method must consistently return the same integer, provided no information used in equals comparisons on the object is modified.


1 Answers

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}))
like image 120
Paul Boddington Avatar answered Nov 15 '22 13:11

Paul Boddington