Understanding TreeSet when compareto returns 0

不羁岁月 提交于 2019-12-30 07:18:12

问题


I have created a Student class like this:

public class Student implements Comparable<Student> {

    private String firstName;
    private String lastName;

    public Student(String firstName, String lastName) {
        this.firstName = firstName;
        this.lastName = lastName;
    }

    // Getters & Setters follow here...

    @Override
    public int compareTo(Student student) {
        int hash = this.firstName.compareTo(student.firstName);
        return hash;
    }

    @Override
    public String toString() {
        return "Student [firstName=" + firstName + ", lastName=" + lastName
                + "]";
    }

}

This is my test class where I just add elements to my TreeSet:

public class SortedSetExample1 {
    public static void main(String[] args) {
        SortedSet<Student> set = new TreeSet<Student>();
        set.add(new Student("A1","A2"));
        set.add(new Student("B1","B2"));
        set.add(new Student("A1","B2"));
        set.add(new Student("A2","B2"));
        System.out.println(set);
    }
}

As per my program the output is:

[Student [firstName=A1, lastName=A2], Student [firstName=A2, lastName=B2], Student [firstName=B1, lastName=B2]]

In my test class I am adding Student objects to TreeSet, and also I have not overridden the hashCode & equals methods. So I was expecting that the TreeSet will hold all the 4 objects but I can also see that it contains 3 objects. Can you please explain why new Student("A1","B2") is not part of my TreeSet?

Also as per the Java docs for TreeSet here, it says:

Adds the specified element to this set if it is not already present. More formally, adds the specified element e to this set if the set contains no element e2 such that (e==null ? e2==null : e.equals(e2)). If this set already contains the element, the call leaves the set unchanged and returns false.

As I have not overridden the equals method then why the collection is not having all the four elements?


回答1:


As java.util.TreeSet says:

a TreeSet instance performs all element comparisons using its compareTo (or compare) method, so two elements that are deemed equal by this method are, from the standpoint of the set, equal

Kudos to @Jon Skeet.




回答2:


That is because TreeSet uses compareTo (or Comparator.compare) to test whether two elements are equal. This is what the docs say about it.

Note that the ordering maintained by a set (whether or not an explicit comparator is provided) must be consistent with equals if it is to correctly implement the Set interface. (See Comparable or Comparator for a precise definition of consistent with equals.) This is so because the Set interface is defined in terms of the equals operation, but a TreeSet instance performs all element comparisons using its compareTo (or compare) method, so two elements that are deemed equal by this method are, from the standpoint of the set, equal. The behavior of a set is well-defined even if its ordering is inconsistent with equals; it just fails to obey the general contract of the Set interface.




回答3:


Since you have compared only first name in compareTo method, you need

 @Override
public int compareTo(Student student) {
    int comp = this.firstName.compareTo(student.firstName);
    if(comp==0) return this.lastName.compareTo(student.lastName);
    return comp;
}

when compareTo returns 0, treeSet assumes that its duplicate.




回答4:


Well, your treeset key values are "A1","B1","A1","A2". Even though you are not overriding equals and hashcode still the default hashcode for "A1" will be same and hence the treeset will consider this key as duplicate key so you will not be able to enter "A1","B2"



来源:https://stackoverflow.com/questions/31334698/understanding-treeset-when-compareto-returns-0

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