Java LinkedHashSet

I studied at OCJP (formerly SCJP) and I came across the following example that uses LinkedHashSet:

public class Test{ int size; public Test(int s){ this.size = s; } @Override public boolean equals(Object obj) { return (this.size == ((Test)obj).size); } public static void main(String[] args) { LinkedHashSet<Test> s = new LinkedHashSet<Test>(); s.add(new Test(1)); s.add(new Test(2)); s.add(new Test(1)); System.out.println(s.size()); } } 

Now the question is what is displayed if:
1) the implementation remains as it is 2) the hashCode override is inserted into the Test class as follows:

 public int hashCode() {return size/5}; 

Running and compiling the code means that the size of the set in the first case is 3, and in the second - 2. Why?

In case 1, although the equals method is overridden, it is never called. Does this mean that the add () method does not check the equality of the object if the hashCode method is not overridden?
In case 2, the hash code with this implementation and the set of tasks of Test objects always returns the same number. How is this different from the default hashCode implementation and why does it invoke equals calls?

+6
source share
2 answers

If you do not override hashCode() , then each of your instances will have hashcode computed from some predefined Hashing algorithm in the Object class. Thus, all your instances will probably have different hash values ​​(this is not the case yet). So, each instance will go into its bucket.

Now, even if you override the equals() method to make two instances equal based on some attribute, their hash codes are still different.

So, two instances with different hash codes can never be equal. Thus, the size of the set is 3. Since it has no duplicates.


But when you override hashCode() with the following implementation: -

 public int hashCode() {return size/5}; 

It will return the same value for the same size . This way, instances with the same size value will have the same hash codes, and also, since you compared them in the equals method based on size , therefore they will be equal and therefore they will be considered duplicate in your Set and therefore will be deleted . So Set.size() is 2.

Moral : - You should always override hashCode() whenever you override the equals() method in order to maintain a common contract between the two methods.

General contract between hashcode and equals method : -

  • When two objects are equal, their hash code must be equal
  • If two objects are not equal, their hash code may be equal
  • The hashCode algorithm should always generate the same value for the same object.
  • If hashCode for two objects is different, they will not be equal
  • Always use the same attributes to calculate the hashcode that you used to compare two instances

It is strongly recommended to read at least once : -

+10
source

Hashing structures rely on the hashing algorithm that hashCode() introduces in java. When you put something in a HashMap (or LinkedHashSet in your case), jvm calls hashCode() objects that are inserted into this structure. If it is not overridden, the default class hashCode() from Object will be used and it is inefficient - all objects fall into their own buckets.

When you override hashCode() method shown in your example, all the objects in your example fall into the same bucket. And then (when adding them one by one) compare with equals() . Therefore, in the first case (when equals() not called) you get a size of 3, and in the second - 2.

+2
source

All Articles