Why do I need to override the equals and hashCode

2018-12-30 23:27发布

Recently I read through this Developer Works Document.

The document is all about defining hashCode() and equals() effectively and correctly, however I am not able to figure out why we need to override these two methods.

How can I take the decision to implement these methods efficiently?

29条回答
柔情千种
2楼-- · 2018-12-31 00:07

Assume you have class (A) that aggregates two other (B) (C), and you need to store instances of (A) inside hashtable. Default implementation only allows distinguishing of instances, but not by (B) and (C). So two instances of A could be equal, but default wouldn't allow you to compare them in correct way.

查看更多
君临天下
3楼-- · 2018-12-31 00:08

You must override hashCode() in every class that overrides equals(). Failure to do so will result in a violation of the general contract for Object.hashCode(), which will prevent your class from functioning properly in conjunction with all hash-based collections, including HashMap, HashSet, and Hashtable.


   from Effective Java, by Joshua Bloch

By defining equals() and hashCode() consistently, you can improve the usability of your classes as keys in hash-based collections. As the API doc for hashCode explains: "This method is supported for the benefit of hashtables such as those provided by java.util.Hashtable."

The best answer to your question about how to implement these methods efficiently is suggesting you to read Chapter 3 of Effective Java.

查看更多
人间绝色
4楼-- · 2018-12-31 00:10

It is useful when using Value Objects. The following is an excerpt from the Portland Pattern Repository:

Examples of value objects are things like numbers, dates, monies and strings. Usually, they are small objects which are used quite widely. Their identity is based on their state rather than on their object identity. This way, you can have multiple copies of the same conceptual value object.

So I can have multiple copies of an object that represents the date 16 Jan 1998. Any of these copies will be equal to each other. For a small object such as this, it is often easier to create new ones and move them around rather than rely on a single object to represent the date.

A value object should always override .equals() in Java (or = in Smalltalk). (Remember to override .hashCode() as well.)

查看更多
荒废的爱情
5楼-- · 2018-12-31 00:12

hashCode() :

If you only override hash-code method nothing will happen. Because it always return new hashCode for each object as an Object class.

equals() :

If you only override equal method, a.equals(b) is true it means the hashCode of a and b must be same but not happen. Because you did not override hashCode method.

Note : hashCode() method of Object class always return new hashCode for each object.

So when you need to use your object in the hashing based collection, must override both equals() and hashCode().

查看更多
怪性笑人.
6楼-- · 2018-12-31 00:12

hashCode() method is used to get a unique integer for given object. This integer is used for determining the bucket location, when this object needs to be stored in some HashTable, HashMap like data structure. By default, Object’s hashCode() method returns and integer representation of memory address where object is stored.

The hashCode() method of objects is used when we insert them into a HashTable, HashMap or HashSet. More about HashTables on Wikipedia.org for reference.

To insert any entry in map data structure, we need both key and value. If both key and values are user define data types, the hashCode() of the key will be determine where to store the object internally. When require to lookup the object from the map also, the hash code of the key will be determine where to search for the object.

The hash code only points to a certain "area" (or list, bucket etc) internally. Since different key objects could potentially have the same hash code, the hash code itself is no guarantee that the right key is found. The HashTable then iterates this area (all keys with the same hash code) and uses the key's equals() method to find the right key. Once the right key is found, the object stored for that key is returned.

So, as we can see, a combination of the hashCode() and equals() methods are used when storing and when looking up objects in a HashTable.

NOTES:

  1. Always use same attributes of an object to generate hashCode() and equals() both. As in our case, we have used employee id.

  2. equals() must be consistent (if the objects are not modified, then it must keep returning the same value).

  3. Whenever a.equals(b), then a.hashCode() must be same as b.hashCode().

  4. If you override one, then you should override the other.

http://parameshk.blogspot.in/2014/10/examples-of-comparable-comporator.html

查看更多
刘海飞了
7楼-- · 2018-12-31 00:13

In the example below, if you comment out the override for equals or hashcode in the Person class, this code will fail to look up Tom's order. Using the default implementation of hashcode can cause failures in hashtable lookups.

What I have below is a simplified code that pulls up people's order by Person. Person is being used as a key in the hashtable.

public class Person {
    String name;
    int age;
    String socialSecurityNumber;

    public Person(String name, int age, String socialSecurityNumber) {
        this.name = name;
        this.age = age;
        this.socialSecurityNumber = socialSecurityNumber;
    }

    @Override
    public boolean equals(Object p) {
        //Person is same if social security number is same

        if ((p instanceof Person) && this.socialSecurityNumber.equals(((Person) p).socialSecurityNumber)) {
            return true;
        } else {
            return false;
        }

    }

    @Override
    public int hashCode() {        //I am using a hashing function in String.java instead of writing my own.
        return socialSecurityNumber.hashCode();
    }
}


public class Order {
    String[]  items;

    public void insertOrder(String[]  items)
    {
        this.items=items;
    }

}



import java.util.Hashtable;

public class Main {

    public static void main(String[] args) {

       Person p1=new Person("Tom",32,"548-56-4412");
        Person p2=new Person("Jerry",60,"456-74-4125");
        Person p3=new Person("Sherry",38,"418-55-1235");

        Order order1=new Order();
        order1.insertOrder(new String[]{"mouse","car charger"});

        Order order2=new Order();
        order2.insertOrder(new String[]{"Multi vitamin"});

        Order order3=new Order();
        order3.insertOrder(new String[]{"handbag", "iPod"});

        Hashtable<Person,Order> hashtable=new Hashtable<Person,Order>();
        hashtable.put(p1,order1);
        hashtable.put(p2,order2);
        hashtable.put(p3,order3);

       //The line below will fail if Person class does not override hashCode()
       Order tomOrder= hashtable.get(new Person("Tom", 32, "548-56-4412"));
        for(String item:tomOrder.items)
        {
            System.out.println(item);
        }
    }
}
查看更多
登录 后发表回答