Denys S.
Denys S.

Reputation: 6525

Simple HashSet contains misunderstanding

I don't understand why HashSet returns false for next example. Code:

import java.util.*;

public class Name {
    private String first, last;

    public Name(String first, String last){
        this.first = first; 
        this.last = last;
    }

    public boolean equals(Name n){
        return n.first.equals(first) && n.last.equals(last);
    }

    public int hashCode(){
        return 31*first.hashCode()+last.hashCode();
    }

    public static void main(String[] args){
        Set<Name> s = new HashSet<Name>();
        Name n1 = new Name("Donald", "Duck");
        Name n2 = new Name("Donald", "Duck");
        s.add(n1);

        System.out.print("HashCodes equal: ");
        System.out.println( n1.hashCode() == n2.hashCode());
        System.out.print("Objects equal: ");
        System.out.println( n1.equals(n2) );

        System.out.print("HashSet contains n1: ");
        System.out.println(s.contains(n1));

        System.out.print("HashSet contains n2: ");
        System.out.println(s.contains(n2));
    }

}

Result:

HashCodes equal: true
Objects equal: true
HashSet contains n1: true
HashSet contains n2: false

Excerpt from HashSet contains method description:

Returns true if this set contains the specified element. More formally, returns true if and only if this set contains an element e such that (o==null ? e==null : o.equals(e)).

Question: why does it return false for both objects even though they are both not null and they are both equal in terms of hesh and value?

Upvotes: 1

Views: 206

Answers (2)

sergeyan
sergeyan

Reputation: 1183

You have an error with overriding Object's equals method.

    public boolean equals(Name n){

is just a method. The correct contract is:

    public boolean equals(Object o){
     // .....
    }

Upvotes: 3

Alexis C.
Alexis C.

Reputation: 93892

Because you did'nt override the equals method herited from the Object class.

    @Override
    public boolean equals(Object o){
        Name n = (Name)o;
        return n.first.equals(first) && n.last.equals(last);
    }

Output (demo here):

HashCodes equal: true
Objects equal: true
HashSet contains n1: true
HashSet contains n2: true

Upvotes: 8

Related Questions