HashSet contains() method

让人想犯罪 __ 提交于 2019-12-22 05:18:37

问题


I executed below code and found the output was false.

import java.util.Set;
import java.util.HashSet;

public class Name {
    private String first, last;

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

    public boolean equals(Object o) {
        if (!(o instanceof Name))
            return false;
        Name n = (Name) o;
        return n.first.equals(first) && n.last.equals(last);
    }

    public static void main(String[] args) {
        Set<Name> s = new HashSet<Name>();
        s.add(new Name("Donald", "Duck"));
        System.out.println(s.contains(new Name("Donald", "Duck")));
    }
}

I want to know how it behaves and why output is false.


回答1:


You need to override hashCode() method also along with equals(). Both the methods are used for proper functionality of HashSet, so must be overriden in a user-defined class if you are making that class as a key, else hashCode() of Object class is getting used and no two different objects can be considered as same as their hashCode() would always be different, and will for sure return falsealways in the case of contains().




回答2:


In order for a HashSet (or HashMap, for that matter) to properly locate your object, you need to override the hashCode() method so that two object which are equal have the same hashCode. The canonical way of doing this looks like this (assuming first and last can't be null, like your equals method assumes:

@Override
public int hashCode() {
    final int prime = 31;
    int result = 1;
    result = prime * result + first.hashCode();
    result = prime * result + last.hashCode();
}



回答3:


Any Hash based data structure implementation (collection) in Java checks duplication based on two things :

1 : if equals method returns true for any of elements which are already stored in collection.

2 : if the hashCode method returns the same integer value for any of elements which are already stored in collection.

So in your case you haven't overridden the hashCode method, it means it will try to check hashCode equality using hashCode method default implementation of Object class which is not aware of your last and first variables.

I hope it helps.




回答4:


Your equals() method is ok, but you have missed to override hashCode() method, just override the hashCode() method, it will work. And don't forgot you always need to override both equals() and hashCode() or none of them to get the correct behavior. If you are planing to use your objects as a key in hashing mechanism than you must override both of them.

@Override
public int hashCode() {
    final int prime = 31;
    int result = 1;
    result = prime * result + ((first == null) ? 0 : first.hashCode());
    result = prime * result + ((last == null) ? 0 : last.hashCode());
    return result;
}



回答5:


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




回答6:


You can also see how your code will be executed.

  1. When you try to add element in set it calls the hash code and it gets bucket.

  2. Once you get the hash value from hash code the overrided equals will be run for all those who are having same hash token.

Hope this helps.



来源:https://stackoverflow.com/questions/31470515/hashset-contains-method

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!