首页 文章

比较时理解TreeSet返回0

提问于
浏览
3

我创建了一个这样的Student类:

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
                + "]";
    }

}

这是我的测试类,我只是在我的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);
    }
}

根据我的程序,输出是:

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

在我的测试类中,我将 Student 个对象添加到 TreeSet ,而且我还没有覆盖 hashCodeequals 方法 . 所以我期待 TreeSet 将保存所有4个对象,但我也可以看到它包含3个对象 . 你能解释为什么 new Student("A1","B2") 不属于我的 TreeSet 吗?

另外,根据Java docs for TreeSet,它说:

如果指定的元素尚不存在,则将其添加到此集合中 . 更正式地,如果集合不包含元素e2,则将指定的元素e添加到该集合中(e == null?e2 == null:e.equals(e2)) . 如果此set已包含该元素,则调用将保持set不变并返回false .

因为我没有覆盖 equals 方法,那么为什么集合没有所有四个元素?

4 回答

  • 10

    正如java.util.TreeSet所说:

    TreeSet实例使用compareTo(或compare)方法执行所有元素比较,因此从集合的角度来看,这个方法认为相等的两个元素是相等的

    感谢@Jon Skeet .

  • 1

    那是因为 TreeSet 使用 compareTo (或 Comparator.compare )来测试两个元素是否相等 . 这是文档所说的 .

    请注意,如果要正确实现Set接口,则由set维护的排序(无论是否提供显式比较器)必须与equals一致 . (有关与equals一致的精确定义,请参阅Comparable或Comparator . )这是因为Set接口是根据equals操作定义的,但TreeSet实例使用compareTo(或compare)方法执行所有元素比较,因此从集合的角度来看,通过这种方法被认为相等的元素是相等的 . 集合的行为即使其排序与equals不一致也是明确定义的;它只是不遵守Set接口的一般 Contract .

  • -1

    由于您只比较了compareTo方法中的第一个名称,因此您需要

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

    当compareTo返回0时,treeSet假定它是重复的 .

  • 1

    那么,你的树形键值是“A1”,“B1”,“A1”,“A2” . 即使你没有覆盖equals和hashcode,“A1”的默认哈希码也是相同的,因此treeset会将此键视为重复键,因此您将无法输入“A1”,“B2”

相关问题