简体   繁体   中英

Is overriding hashCode and equals a necessity when adding non-primitive objects to a TreeSet?

I'm following a tutorial to better understand Natural Ordering, using TreeSet and the Comparable interface.

The tutorial tells me that, to add non-primitive custom objects to Sets, I need to implement equals() and hashCode() . However, even without implementing these methods I'm able to compile and run the code (as below). I am using IntelliJ with Java 8.

Is overriding equals() and hashCode() absolutely necessary when working with TreeSets (SortedSet interface) and natural ordering?

class My_Person implements Comparable<My_Person>{
    private String name;

    public My_Person(String name) {
        this.name = name;
    }

    public String toString() {
        return name;
    }

//    @Override
//    public boolean equals(Object o) {
//        if (this == o)
//            return true;
//        if (o == null || getClass() != o.getClass())
//            return false;
//        My_Person my_person = (My_Person) o;
//        return Objects.equals(name, my_person.name);
//    }
//
//    @Override
//    public int hashCode() {
//        return Objects.hash(name);
//    }

    @Override
    public int compareTo(My_Person person) {
        return name.compareTo(person.name);
    }
}

public class NaturalOrdering {

    public static void main(String[] args) {

        List<My_Person> list = new ArrayList<>();
        Set<My_Person> set = new TreeSet<>();   

        addElement(list);
        addElement(set);

        Collections.sort(list);

        showElement(list);
        System.out.println("\n");
        showElement(set);

    }


    private static void addElement(Collection<My_Person> collection) {
        collection.add(new My_Person("Joe"));
        collection.add(new My_Person("Sue"));
        collection.add(new My_Person("Juliet"));
        collection.add(new My_Person("Clare"));
        collection.add(new My_Person("Mike"));
    }


    private static void showElement(Collection<My_Person> collection) {
        for(My_Person element: collection) {
            System.out.println(element);
        }
    }
}

This depends on your requirements for equality. If you don't override equals and hashCode , two objects are defined as equal if and only if they are identical (ie the same object). If you need some other definition for equality you must override the methods.

It is not "absolutely necessary", but then you may get unexpected/wrong output if you don't do so. So if you don't override them, it may still work sometimes, but it may fail too. So just to be safe, better override it. It will fail if you need to check equality. But if you are only concerned with sorting of the stored objects as per your own defined logic in compareTo method, then I think there is no need to override equals or hashcode.

Its not required by TreeSet or for that matter any Set. But Set is by nature collection of unique objects. For primitive types, Java has way to know whether two objects are same or not. For non-primitive user has to tell Java on how to know whether two objects are same or not and way is to override equals and hashcode methods which are invoked by Set#add method to determine the object being added already exists in the set or not. So if you need a functional unique objects in your Set, you should implement equals and hashcode methods. Hope this helps. This is a good read on the same topic.

You have the source code for TreeSet (and TreeMap which TreeSet uses under the hood). You can clearly see that TreeSet (and TreeMap) rely on compareTo() and not hashCode().

On the other hand, the HashSet (and HashMap which HashSet uses under the hood) does use hashCode() and equals(). No big surprise, considering that they are named Hash Set and Hash Map.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM