public class Main {

    public static void main(String[] args) {
        String str1="shrey";
        String str2="shrey";
        String str3=new String("shrey");
        System.out.println(str1.hashCode());
        System.out.println(str2.hashCode());
        System.out.println(str3.hashCode());
    }
}

output = same hashcode of all str1, str2, str3

Java uses string pool. I know it. str1 and str2 are created using string literal so they should refer to same object and hence will generate the same hashcode but, str3 is created using new keyword, so I was expecting hashcode of str3 to be different but it came out to be same. Why?

4

There are 4 best solutions below

0
Stephen C On

Your question is based on false assumptions:

Since java creates a new object when new keyword is used,

Correct

... and every object has unique hashcode,

Incorrect! Nothing in any of the Java specifications states that hashcodes are unique. In fact, the closest it comes to that is this line from the javadocs for Object.

"Implementation Requirements: As far as is reasonably practical, the hashCode method defined by class Object returns distinct integers for distinct objects."

That says try to make them distinct if you can ... but it does not guarantee that they will be distinct. Indeed, it is provably impossible to guarantee that in the context of Java.

... then why here it is giving same hashcode output?

That is nothing to do with Object::hashCode. You code is actually calling the String::hashCode, and that is specified to return a value that is independent of the string's identity. The String javadoc states:

"Returns a hash code for this string. The hash code for a String object is computed as

s[0]*31^(n-1) + s[1]*31^(n-2) + ... + s[n-1]

using int arithmetic, where s[i] is the ith character of the string, n is the length of the string, and ^ indicates exponentiation."

Your strings all have the same length and the same characters, so that means that String::hashCode will give the same result.

We can also infer that this should be the case from the properties of hashCode and equals as set out in the Object javadocs. In concise terms:

s1.equals(s2) == true  implies  s1.hashCode() == s2.hashCode()
0
AudioBubble On

The Java programming language equals and hashCode contract states that two equal objects according to equals(Object object) method must have equal hash codes, while two objects with equal hash codes could be different from one to another.

There are details about the hashCode method contract in Java documentation of Object class of the Java programming language version of your preference.

0
M. Justin On

Your assertion that "every object has a unique hashcode" is incorrect. Rather, the rule is that equal objects must have the same hash code. Unequal objects may or may not have different hash codes (though for performance reasons it is important most unequal objects do).

Per the contract of hashCode, objects which are equal according to equals must have equal hash codes:

If two objects are equal according to the equals method, then calling the hashCode method on each of the two objects must produce the same integer result.

Per the String Javadocs, two String values are considered equal according to equals when they represent the same sequence of characters:

The result is true if and only if the argument is not null and is a String object that represents the same sequence of characters as this object.

"shrey" and new String("shrey") represent the same sequence of characters (namely, {'s', 'h', 'r', 'e', 'y'}). Therefore, they are equal according to equals and must have the same hash code.

Finally, to add a little more context, the Javadocs for hashCode explain that two unequal objects may have the same hash code, though doing so comes with performance consequences:

It is not required that if two objects are unequal according to the equals method, then calling the hashCode method on each of the two objects must produce distinct integer results. However, the programmer should be aware that producing distinct integer results for unequal objects may improve the performance of hash tables.

0
Christian Meyer On

#hashcode will give you the same hash value for all objects that are the same in terms of their literal value. So any string with the value "eclips3", no matter how it is constructed, and whether or not #intern is applied, will have the same hashcode.

What is more suited for your purposes is System.identityHashCode(stringObj), which is basically the original implementation of #hashcode by Object before it gets overridden. As a result, we can use this method to distinguish references [stored in separate memory locations] even when they have the same literal value.

Here a basic demo to help you get a better idea:

        String s1 = "eclips3";
        String s2 = new String("eclips3");
        String s3 = new String("eclips3");
        String s4 = s2.intern();
        String s5 = new String("eclips3").intern();

        System.out.println(System.identityHashCode(s1));
        System.out.println(System.identityHashCode(s2));
        System.out.println(System.identityHashCode(s3));
        System.out.println(System.identityHashCode(s4));
        System.out.println(System.identityHashCode(s5));
        
        System.out.println("s1 == s2? " + String.valueOf(s1==s2));
        System.out.println("s1 == s3? " + String.valueOf(s1==s3));
        System.out.println("s1 == s4? " + String.valueOf(s1==s4));
        System.out.println("s1 == s5? " + String.valueOf(s1==s5));
        System.out.println("s2 == s3? " + String.valueOf(s2==s3));
        System.out.println("s2 == s4? " + String.valueOf(s2==s4));
        System.out.println("s2 == s5? " + String.valueOf(s2==s5));
        System.out.println("s3 == s4? " + String.valueOf(s3==s4));
        System.out.println("s3 == s5? " + String.valueOf(s3==s5));
        System.out.println("s4 == s5? " + String.valueOf(s4==s5));

Results on my system:

95980430
1478835287
12006451
95980430
95980430
s1 == s2? false
s1 == s3? false
s1 == s4? true
s1 == s5? true
s2 == s3? false
s2 == s4? false
s2 == s5? false
s3 == s4? false
s3 == s5? false
s4 == s5? true