TreeSet example

主宰稳场 提交于 2019-12-11 01:41:42

问题


Why the 3rd object is not being added to the treeset here though it is a different one?

import java.util.*;

class Student implements Comparable<Student>{
public String fn,ln;
public Student(String fn,String ln){
    this.fn=fn;
    this.ln=ln;
}

//overiding equals

public boolean equals(Object o) {
    if (!(o instanceof Student))
        return false;
    Student s=(Student) o;
    if(this==s)
        return true;
    if(this.fn.equals(s.fn) && this.ln.equals(s.ln))
        return true;
    return false;
}

//overiding hashcode

public int hashCode() {
    return fn.hashCode()+ln.hashCode();
}


//overiding compareTo

public int compareTo(Student o) {

    return this.fn.compareTo(o.fn);
}
  }

public class Practice {


public static void main(String[] args) {
    Student st1=new Student("Girish","J");
    Student st2=new Student("Master","M");
    Student st3=new Student("Girish","Jay");
    Set S=new TreeSet();

           //adding 3 different student objects

    System.out.println(S.add(st1));
    System.out.println(S.add(st2));
    System.out.println(S.add(st3));
    Iterator sitr=S.iterator();
    while(sitr.hasNext())
    {
        Student stu=(Student) sitr.next();
        System.out.println(stu.fn+" "+stu.ln);
    }


}

 }

Output:

true
true
false
Girish J
Master M

回答1:


Your comparator function only uses fn:

public int compareTo(Student o) {
    return this.fn.compareTo(o.fn);
}

TreeSet only uses ordering comparisons - it doesn't use hashCode() and equals().

By this comparison, st1 and st3 are equal (s1.compareTo(s3) will return 0) therefore st3 isn't added to the set.

If you want to maintain the distinction, you should probably compare fn and then use ln if the fn values are the same:

public int compareTo(Student o) {
    int fnResult = this.fn.compareTo(o.fn);
    return fnResult == 0 ? ln.compareTo(o.ln) : fnResult;
}



回答2:


Your observations are correct that TreeSet does not use .equals and .hashcode for comparison.

From the javadocs:

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. 

Basically, they are saying that for TreeSet, equality is determined not through .equals, but through .compareTo on the Comparable interface. Note that .compareTo should always be in line with .equals, meaning that if a.equals(b), then a.compareTo(b) == 0.

This has to do with the fact that TreeSet is an implementation of SortedSet. As such, it needs .compareTo in order to determine order, since .equals is not enough in that case.

PS: If you do not want to implement Comparable (which sometimes you can't since you might not always control the code of the objets), you could always pass a Comparator to the TreeSet constructor.




回答3:


Your comparison is only using the fn value...

public int compareTo(Student o) {
    return this.fn.compareTo(o.fn);
}

Which fails for the 3rd Student because the first name is identical to the 1st Student

You need to adjust your code to compare both the fn and the ln values...

public int compareTo(Student o) {
    int firstNameComparison = this.fn.compareTo(o.fn);
    if (firstnameComparison != 0){
        // the first names are different
        return firstNameComparison;
    }
    else {
        // the first names are the same, so compare the last name
        return this.ln.compareTo(o.ln);
    }
}

This code compares the fn values first. If they are identical, it then compares the ln values.



来源:https://stackoverflow.com/questions/11082197/treeset-example

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