1

Possible Duplicate:
Overriding equals and hashCode in Java

For contains should we override both hashcode and equals for hashset in java?

import java.lang.Math;
import java.util.HashSet;
class Hello{

    public String name= ""; 

    Hello(String name){
        this.name = name;   
    }


    public static void main(String args[]){

        Hello h1 = new Hello("first");
        Hello h2 = new Hello("second");
        Hello h3 = new Hello("third");
        Hello h4 = new Hello("fourth");
        Hello h5 = new Hello("fourth");

        HashSet hs = new HashSet(); 
        hs.add(h1);
        hs.add(h2);
        hs.add(h3);
        hs.add(h4);
        hs.add(h5);
        hs.add(h5);
        hs.add(null);

        System.out.println("elements in hashset"+hs);
        // System.out.println("elements in hashset"+hs.contains());
        System.out.println("elements in hashset"+hs.contains(new Hello("fourth")));

    } 

    /*public boolean equals(Object obj){
        System.out.println(name+"==========="+((Hello)obj).name);
        if(name.equals(((Hello)obj).name))
            return true;
        else
            return false;
    }*/

    public int hashCode(){    
        return name.hashCode();    
    }    
}
Community
  • 1
  • 1
crackerplace
  • 4,787
  • 7
  • 27
  • 39
  • Similar questions have been asked many times, one of them is this one: [Overriding equals and hashCode in Java](http://stackoverflow.com/questions/27581/overriding-equals-and-hashcode-in-java) – Sean Patrick Floyd May 09 '11 at 11:10
  • @Sean Patrick Floyd .. I have a decent understandng but quite confused .. Let me summarize .. For HashMaps we need to override ..hashcode (so that whileinvoking get the hashcode finds the bucket in which value is present) and equals (to comapre the keys as we might have many key value pairs in a single bucket).If we dont override hashcode and equals hashmap wll definitely not work that is when you say get after inserting the pair ..u might not get the value ... – crackerplace May 09 '11 at 11:45
  • @Sean Patrick Now coming to hashSets,adding cutom class objects to the set we need to override the hashcode method so that the duplicates are not inserted ... but why equals ? ..Fro a bucket we have one hashcode and in hashset a bucket will contain only one ..corrct me if i am wrong elemnt – crackerplace May 09 '11 at 11:56

6 Answers6

3

I don't see any detail about the question, but yes, you should override hashCode() and equals() to properly compare objects for collections.

Joseph Ottinger
  • 4,711
  • 1
  • 20
  • 23
  • The point is When i just override the equals method ,the contains is returning false.why do we need to even override the hashcode method for contains to return true ? – crackerplace May 09 '11 at 11:52
  • Both of them shud be overided for hash maps but i culdnt understand why for hashsets .. as in a hashset the hashcode fo the key is calculated and equals is not used .. – – crackerplace May 09 '11 at 11:53
  • No, both are used. if the hash is the same, equals() will be called. – Joseph Ottinger May 09 '11 at 12:59
1

If you override either hashCode or equals, you must override them both. It says that in the Javadocs for java.lang.Object, and it's definitely true.

Ernest Friedman-Hill
  • 77,245
  • 10
  • 138
  • 182
  • thst a generci statemnet ,I doubt if its infact essential even for sets – crackerplace May 09 '11 at 11:37
  • It is absolutely essential. You need to look up the details of how a HashSet works -- or generally, what *hashing* is. In short, the objects are put into piles (called `buckets`) according to some function (called the `hash value`) of their hash code. The `equals()` comparison is then done only among the objects in the bucket with the same hash value as the key object. That's kind of the whole point -- that reduced number of comparisons is why hashed collections are fast. Anyway, if `hashCode()` isn't overridden, objects that are `equals()` may not be put into the same bucket! – Ernest Friedman-Hill May 09 '11 at 12:01
  • @Ernest Coming to ur point what i understood .. We need to override hashcode for sure otherwise when we insert a refrence(Hello object for ex..Hello("crazy") ) and next time whne I try to check thru contains the key with a new refernce new Hello("crazy") the hashcode will be a new one hence contains cannot find the elemnt in the bucket and in addition same objects might be in diffrnt buckets and hence duplicates ..... – crackerplace May 09 '11 at 12:12
  • @Ernest Now coming to overriding equals ,if i override hashcode and if I dont override equals then contains method will return false always except whne the refrence is saem while insertng and checking its presence .. So practically thers no difference between a hashmap and hashset .as hashset is intrun using hashmap .. i was confused as in some interviews they say for hashsets just equals overiding is enuff .. – crackerplace May 09 '11 at 12:13
  • Apparently "some interviews" are conducted by morons, then. – Ernest Friedman-Hill May 09 '11 at 12:15
  • @Ernest Excllnt Thanks .. its clear now .. both abt the interviewers and Sets :-) – crackerplace May 09 '11 at 12:20
  • You need `hashCode` for hash-based sets, not for comparision based sets, and also not for sets which only use the equals method (like CopyOnWriteArraySet). IdentityHashSet uses neither equals nor hashCode. – Paŭlo Ebermann May 09 '11 at 12:42
  • @Paŭlo Ebermann Ohh .. this is new to me .. So for Hashset we need both of thm defntely .. ? for the above u mentiond dont they store elemnts in buckets .. or dnt they use hashng .. .. examples of comparision based buckets .. – crackerplace May 09 '11 at 12:56
  • @Paŭlo Ebermann -- But if you override `equals()` you should *always* override `hashCode()` as well, or you've created a class that will mysteriously fail to work when someone decides that `HashSet` will work better than `TreeSet` in a given circumstance. Your implication that it's OK to only override `equals()` if that's all that will be called in a certain circumstance is both dangerous and wrong. – Ernest Friedman-Hill May 09 '11 at 12:58
  • @whataheck, please don't be fooled. Overriding both these methods is an important rule. Don't fall into the trap of thinking "Oh, I only need the one, so I won't bother with the other." If you override one of these methods you *must* override the other. End of discussion. – Ernest Friedman-Hill May 09 '11 at 13:01
  • @Ernest Friedman-Hill Thanks for the concern .. But you misinterpreted...We need to definietly override both and now I am sure as i understood throughly .. What Paulo was mentioning was that for some sets other than hashmap and hashsets .. u dont need to override hashcode such as identity which doesnt use any .. This is what I get ... – crackerplace May 09 '11 at 13:06
  • @Ernest Friedman-Hill From the API .. Identity hashcode is for refernce based cmparision scenario and hnce obviuosly overriding equals is not needed ... But i think we should override hashcode .. – crackerplace May 09 '11 at 13:11
  • Yes, you should always override both (or none), even if in some cases only one of them (or none at all) are used. – Paŭlo Ebermann May 09 '11 at 14:17
  • @whataheck: It makes no sense to override hashCode and not overriding equals. If you use reference identity as your equality relation, the default hashCode() does fine, no need to override. Overriding it can even degrade your HashMap performance. – Paŭlo Ebermann May 09 '11 at 14:19
  • @Paulo I meant the same for hashmaps hashsets .. we definitely need to override both .. In Some cases as for reference based comparision we need not override hashcode as the default one wud suffice .. Anywayz this thread helped me a lot .. ..Thnx Gyz ....Lookng fwd ... ......I Shud thank even my Interviewer .... – crackerplace May 09 '11 at 18:01
0

Yes your Hello class is just wrapping a String but you MUST overwrite hashCode and equals in Hello.

planetjones
  • 11,699
  • 3
  • 47
  • 51
0

Yes.

Because HashSet.contains uses containsKey that uses getEntry. It tries to find the key-value pair in the hash and both methods are needed (one for choosing the bucket, other for looking in the internal bucket list).

helios
  • 12,916
  • 2
  • 41
  • 51
  • .For a bucket to be choosen hashcode overriding is fine but why we need to override equals for as incase of a ahshset the key itself is value .. and we dont have any value explicitly .. as in hashmaps .. – crackerplace May 09 '11 at 11:58
  • Because after the hashset/map finds the bucket it must check that the item inside its bucket is the one you are asking for. Even more: hashset (that's implemented with hashmap) is an open hash, so it can hold more than one item in one bucket (a lot of times two items fall into the same bucket). It then must iterate over the bucket item list to find the correct one. If you get into the HashSet/HashMap code you'll find a key.equals(...) in the `HashMap.getEntry` method. – helios May 09 '11 at 13:10
0

You need to override equals if you expect two different Objects to be considered equal. If you use a hash collection, you need to override hashCode() to work the same way.

System.out.println("elements in hashset"+hs.contains(h4); // displays true.
Peter Lawrey
  • 498,481
  • 72
  • 700
  • 1,075
0

By the way, if all your Hello objects shall be regarded as different (e.g. one new Hello("first") should be regarded as different to the next new Hello("first"), you don't have to override equals or hashCode at all, as the default implementations already work fine for this case.

Paŭlo Ebermann
  • 68,531
  • 18
  • 138
  • 203