猿问

我的代码中是声明一个 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;
}

}

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

月关宝盒
浏览 486回答 3
微课
3回答

哆啦的时光机

你的 compareTo 方法返回 0 或 1,返回 0 的时候新 value 替换旧 value,返回 1 的时候,则作为子节点添加到红黑树的右边。 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 40 和 lisi08 19 进行比较,因为你的 compareTo 方法不存在 -1 的返回值。所以 ts 中会保存第四个元素。 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 22 和 lisi08 19 之后,红黑树不需要旋转,root 节点是 lisi02 22,右子节点为 lisi08 19,当你添加最后一个 lisi02 22 的时候是会和第一个 lisi02 22进行比较的。所以 ts 中只会有两个元素。

LEATH

TreeSet 是靠创建时传递的 Comparator 来比较想等性的。 TreeSet(Comparator<? super E> comparator)
随时随地看视频慕课网APP

相关分类

Java
我要回答