我的代码中是声明一个 Tree Set 对象,结果发现加入了“相同”元素。请问是为什么

新手上路,请多包涵

题目描述

题目来源及自己的思路

我的程序里声明了一个 TreeSet 对象 ts,写了一个学生类,当学生的年龄和姓名相同时被认为是相同元素。在 ts 中添加了第一个学生对象与最后一个学生对象时,使这俩个学生对象的姓名和年龄相同,打印结果发现这俩个元素均被输出,ts 大小为 4。

相关代码

import java.util.TreeSet;
public class TreeSetDemo {

public static void main(String[] args) {
    TreeSet<Student> ts = new TreeSet<>();
    ts.add(new Student("lisi02", 22));
    ts.add(new Student("lisi01", 40));
    ts.add(new Student("lisi08", 19));
    ts.add(new Student("lisi02", 22));


    // the first element and the last one are added to ts
    // However, ts belongs to a Set Collection.
    // So I think the last one should not be added to ts.
    // when the second element is annotated, the last one can not be added.
    // Can you explain why?
    
    for (Student e : ts) {
        System.out.println(e.getName() + "\t...\t" + e.getAge());
    }
    System.out.println(ts.size());
}

}

class Student implements Comparable {

private String name;
private int age;
Student(String name, int age) {
    this.name = name;
    this.age = age;
}

public String getName() {
    return name;
}

public int getAge() {
    return age;
}

public int compareTo(Object obj) {
    if (!(obj instanceof Student))
        throw new RuntimeException("Not Student class");
    Student p = (Student) obj;

    // When name and age are the same, the elements are the same
    if (this.name.equals(p.getName()) && p.getAge() == this.age) {
        System.out.println(name + "..." +age);
        return 0;
    } else
        return 1;
}

}

你期待的结果是什么?实际看到的错误信息又是什么?

阅读 2.2k
3 个回答
  1. 你的 compareTo 方法返回 01,返回 0 的时候新 value 替换旧 value,
    返回 1 的时候,则作为子节点添加到红黑树的右边。
  2.  ts.add(new Student("lisi02", 22));
     ts.add(new Student("lisi01", 40));
     ts.add(new Student("lisi08", 19));
     ts.add(new Student("lisi02", 22));

    如果代码是这样的,当你添加完第三个元素 lisi08 19 的时候,红黑树会进行旋转操作,旋转完 root 节点是 lisi01 40,左子节点为 lisi02 22,右子节点为 lisi08 19,当你添加第四个元素时候,只会和 lisi01 40lisi08 19 进行比较,因为你的 compareTo 方法不存在 -1 的返回值。所以 ts 中会保存第四个元素。

  3.  ts.add(new Student("lisi02", 22));
     // ts.add(new Student("lisi01", 40));
     ts.add(new Student("lisi08", 19));
     ts.add(new Student("lisi02", 22));

    当你把第二个元素注释掉,添加完 lisi02 22lisi08 19 之后,红黑树不需要旋转,root 节点是 lisi02 22,右子节点为 lisi08 19,当你添加最后一个 lisi02 22 的时候是会和第一个 lisi02 22进行比较的。所以 ts 中只会有两个元素。

哪里来的相同元素?判断元素是否相同需要实现hashCodeequals方法,很明显你没有实现,所以第一个元素和最后一个元素是不同的元素,Comparable是用来比较大小的,是用来排序的。就好比一辆货车和一辆卡车可以比较大小,但是他们是相同的吗?

TreeSet 是靠创建时传递的 Comparator 来比较想等性的。

TreeSet(Comparator<? super E> comparator)
撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题