overriding equals in Java be sure to rewrite the Hashcode method

Source: Internet
Author: User
Tags data structures
overriding equals in Java be sure to rewrite the Hashcode method

Original Author Blog address: Working with hashcode () and Equals () equals and Hashcode method equals (Object obj): Provided by the object class, Used to determine whether the current object and obj are equal. The default implementation in JDK is based on memory address: Only two objects have equal memory addresses, they are equal hashcode (): The method is provided by the object class, and returns an integer value representing the address of the object in memory, for each object, Hashcode () method to randomly return a unique integer value using the rule if X.equals (y) ==true, then X.hashcode () ==y.hashcode () must also return True

In other words, if you override the Equals method in a class, you must override the Hashcode method

Entity class Ball.java:

public class Ball {

    private int id;
    private String color;

    public Ball (int ID, String color) {
        this.id = ID;
        This.color = color;
    }

    public int getId () {return
        ID;
    }

    public void setId (int id) {
        this.id = ID;
    }

    Public String GetColor () {return
        color;
    }

    public void SetColor (String color) {
        This.color = color;
    }
}
Scenario 1: Equals and Hashcode methods that directly use the object default implementation

Test:

@Test public
void Commonequals () {
    Ball ball1 = new Ball (1, "red");
    Ball  ball2 = new Ball (1, "red");
    System.out.println ("Ball1 hashcode:" + ball1.hashcode ());
    System.out.println ("Ball2 hashcode:" + ball2.hashcode ());
    System.out.println ("Ball1.equals (BALL2):" + ball1.equals (ball2));

Results:

Ball1 hashcode:26947503
ball2 hashcode:22527820
ball1.equals (BALL2): false

Obviously, different objects, hashcode unequal, ball1 and ball2 naturally unequal . Scenario 2: Overriding the Equals method without overriding the Hashcode method

To override the Equals method:

@Override public
boolean equals (Object obj) {
    if (this = = obj) return
        true;
    if (obj = = NULL | | getclass ()!= Obj.getclass ()) return
        false;
    Ball that = (Ball) obj;
    return Id==that.getid ();
}

Results:

Ball1 hashcode:30430942
ball2 hashcode:16191201
ball1.equals (ball2): True

In the Equals method, we use IDs as equal conditions for two objects

If you use ball after you have overridden only equals in ArrayList

@Test public
void Equalswitharraylist () {
    arraylist<ball> ArrayList = new arraylist<> ();
    Ball ball1 = new Ball (1, "red");
    Ball  ball2 = new Ball (1, "red");
    Arraylist.add (BALL1);
    Arraylist.add (BALL2);
    System.out.println ("ArrayList size:" + arraylist.size ());
    System.out.println ("arrayList contains Ball:" + arraylist.contains (new Ball (1, "red"));
}

As if nothing had been found, the ArrayList would have allowed repeating elements

If you use the ball after the rewrite in HashMap

@Test public
void Equalswithhashmap () {
    hashmap<ball, integer> map = new hashmap<> ();
    Ball ball1 = new Ball (1, "red");
    Ball  ball2 = new Ball (1, "red");
    Map.put (BALL1, 1);
    Map.put (ball2,1);
    SYSTEM.OUT.PRINTLN ("Map size:" + map.size ());
    SYSTEM.OUT.PRINTLN ("map contains Ball:" + map.get (new Ball (1, "red"));
}

Results:

Map Size:2
map contains Ball:null

To be reasonable, map size should be 1, and Map.get (new Ball (1, "red") should return 1. Find HashMap's put source:

Public V-Put (K key, V value) {
    if (table = = empty_table) {
        inflatetable (threshold);
    }
    if (key = = null) return
        Putfornullkey (value);
    int hash = hash (key);
    int i = indexfor (hash, table.length);
    for (entry<k,v> e = table[i]; e!= null; e = e.next) {
        Object K;
        if (E.hash = = Hash && ((k = e.key) = = Key | | key.equals (k))) {
            V oldValue = e.value;
            E.value = value;
            E.recordaccess (this);
            Return OldValue
        }
    }

    modcount++;
    AddEntry (hash, key, value, I);
    return null;
}

All right, HashMap's put operation is to compare the equality of hashcode values, and then compare the Equals method, which is considered addentry if the hashcode is not equal. In fact, Ball did not rewrite the Hashcode method, the first new operation, will be allocated in memory different addresses, so map.size=2.

Look again, Map.get () source method:

Hashmap.get () source code public
V get (Object key) {
   if (key = null) return
       getfornullkey ();
   entry<k,v> Entry = Getentry (key);

   return NULL = = entry? Null:entry.getValue ();
}

Final entry<k,v> getentry (Object key) {
  if (size = = 0) {return
      null;
  }

  int hash = (key = null)? 0:hash (key);
  for (entry<k,v> e = table[indexfor (hash, table.length)];
       e!= null;
       E = e.next) {
      Object k;
      if (E.hash = = Hash &&
          (k = e.key) = = Key | | (Key!= null && key.equals (k)
          )) return e;
  }
  return null;
}

You can see that when you take a value, you first compute the object's hashcode value, Map.get (New Ball (1, "red"), the anonymous new Ball (1, "Red"), and the Hashcode method is not rewritten before, and a new hashcode is generated. So the null rewrite Hashcode method is taken out

@Override public
int hashcode () {return
    ID;
}

Run the Equalswithhashmap test case again, and the result:

Map size:1
map contains ball:1

As you can see, the size of this map is 1, indicating that the BALL1 and Ball2 joined are the same instance

It also applies to hashset,hashtable, or other data structures that use the hashcode mechanism as storage

conclusion: After overriding the Equals method, it is mandatory to override the Hashcode method if two objects are equal, then they must have the same hashcode if two objects have the same hashcode, it does not mean they are equal Overriding the Equals method alone will invalidate data in your business that uses hash data structures, such as hashmap,hashset,hashtable ...

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.