如何从TreeSet中删除最旧的Student对象?

时间:2018-10-30 06:04:14

标签: java collections

我正在尝试从TreeSet中删除最老的Student,但是该对象没有被删除。有人可以解释一下如何从我的TreeSet中删除最旧的Student对象吗?

public class Student implements Comparable<Student> {

    private String studentId;
    private String studentAge;

    public Student(String studentId, String studentAge) {
        super();
        this.studentId = studentId;
        this.studentAge = studentAge;
    }

    public String getStudentId() {
        return studentId;
    }

    public void setStudentId(String studentId) {
        this.studentId = studentId;
    }

    public String getStudentAge() {
        return studentAge;
    }

    public void setStudentAge(String studentAge) {
        this.studentAge = studentAge;
    }

    @Override
    public int compareTo(Student o) {
        if (Double.valueOf(studentAge).compareTo(Double.valueOf(o.getStudentAge())) == 0) {
            return 1;
        } else
            return Double.valueOf(studentAge).compareTo(Double.valueOf(o.getStudentAge()));
    }

    @Override
    public boolean equals(Object obj) {
        Student student = (Student) obj;
        return (student.getStudentId().equals(studentId) && student.getStudentAge().equals(studentAge));
    }

    @Override
    public String toString() {
        return "StudentId " + studentId + " Student Age " + studentAge;
    }

}


import java.util.TreeSet;

public class MainApp {

    public static void main(String[] args) {
        TreeSet<Student> studentList = new TreeSet<Student>();
        studentList.add(new Student("10001", "5"));
        studentList.add(new Student("10001", "15"));
        studentList.add(new Student("10001", "25"));
        studentList.add(new Student("10001", "3"));
        studentList.add(new Student("10001", "2"));
        studentList.add(new Student("10001", "1"));
        studentList.add(new Student("10001", "10"));
        studentList.add(new Student("10001", "6"));
        studentList.add(new Student("10001", "7"));
        studentList.add(new Student("10001", "2"));

        System.out.println(studentList.last().getStudentAge());
        System.out.println(studentList);
        Student maxAge = studentList.last();
        System.out.println(studentList.remove(new Student(maxAge.getStudentId(), maxAge.getStudentAge())));
        System.out.println(studentList);

    }

}

4 个答案:

答案 0 :(得分:2)

您的compare方法被简单地说成是错误的。

第一个天真的解决方法:将两个年龄值提取为数字(并使用整数,因为年龄似乎总是以整数形式出现)。然后打电话

return Integer.compare(first, second);

。 (也许您将不得不改变这两个值,具体取决于您希望对集合进行排序的方式)

您当前在值相等时返回1的方法只是假的。

要点是:TreeSet无法正确排序元素,因为您的compareTo()方法在逻辑上已损坏。排序工作完成后,您可以轻松识别集合中的第一个或最后一个元素并将其删除。

但是真正的问题是:您的基础设计是错误的。您会看到,当您有equals()compareTo()时,人们很快就会谈论:平等努力是否应该为compareTo()赋予0?可以归结为:哪些数据输入到您的equals()方法中。想想看:年龄是否对两个人的身份相同?否。您有一个学生 ID 。 ID的性质用于唯一地识别事物。因此:您应该首先真正弄清组成“独特”学生的原因。

我的建议:

  • 仅应使用ID来唯一标识学生。您可以让两个学生和一个学生在一起。您不能有两个具有相同ID但年龄不同的学生对象。因为ID 是学生
  • 从那里,我会从中删除接口,而是实现独立的Comparator<Student>实例。您可以有一个比较器,将两个学生与上升年龄进行比较。还有另一个带有降序。

这是关键点:仅当您具有真正的“自然”排序顺序(例如Integer)时,才使用Comparable。但是人,学生:对它们进行排序取决于上下文如何。也许随着年龄的增长。但是也许以后您添加一个名称,然后您想要对这些名称字符串进行排序。

答案 1 :(得分:2)

正如其他人所说,您的compareTo方法是错误的。当两个实例相等时,永远不要返回1。这是一个小问题。话虽如此,您的compareTo方法是错误的,不仅因为这个原因,而且还因为您正在根据学生的年龄比较他们TreeSetSet,并且集合不能有重复的元素,因此,这意味着您的集合将无法容纳具有相同元素的学生年龄

幸运的是,每个学生都有一个唯一的ID,因此您可以使用此ID断开联系(即,当两个学生的年龄相同时),从而使两个实例的{em> 与{{1 }}方法,即使它们的年龄相同:

compareTo

注意:这是假设年龄为@Override public int compareTo(Student o) { int result = Integer.compare(studentAge, o.getStudentAge()); return result == 0 ? studentId.compareTo(o.getStudentId()) : result; } 类型。

现在,一旦您固定了int方法,就可以安全地使用compareTo的查找方法。要从您的TreeSet中删除最老的学生,您可以使用pollLast方法,该方法正是您想要的:

TreeSet

答案 2 :(得分:1)

很少有观察结果,如果得到纠正,将解决问题。

-为什么年龄为String?请使其为整数或双精度。在这种情况下,您的compareTo方法将是

@Override
public int compareTo(Student o) {
        return this.studentAge.compareTo(o.getStudentAge());
}

-如果您仍然希望使用age作为String,请使用下面的compareTo方法。

@Override
public int compareTo(Student o) {
        return Double.valueOf(studentAge).compareTo(Double.valueOf(o.getStudentAge()));
}

这两种方法都可以解决您的问题。


现在说明:     与其他映射不同(因为集仅是内部映射,希望您知道),所以不会基于equals方法比较键。如果实现了Comparable或Compartor实现,则根据compareTo比较密钥。 由于您的compareTo方法有问题,因此调用remove方法时永远不会找到25岁的学生。

调用remove方法时,它将尝试使用年龄来搜索键,但是由于您的比较从技术上讲永远不会返回0(表示相等),因此永远不会找到对象,因此也不会删除对象。

但是最后一个方法给出了正确的学生值,因为在填充值的情况下compareTo方法将正常工作。.

答案 3 :(得分:0)

建议,equals方法在覆盖..p时应考虑以下条件。

  1. 如果两个对象都指向相同的引用,则默认情况下它们相等,因此无需进行内容比较
  2. 它应在运行时处理ClassCastException和NullPointerException,您可以使用instanceof运算符来实现。

添加了Stringequals方法供参考

  public boolean equals(Object anObject) {
    if (this == anObject) {
        return true;
    }
    if (anObject instanceof String) {
        String anotherString = (String)anObject;
        int n = value.length;
        if (n == anotherString.value.length) {
            char v1[] = value;
            char v2[] = anotherString.value;
            int i = 0;
            while (n-- != 0) {
                if (v1[i] != v2[i])
                    return false;
                i++;
            }
            return true;
        }
    }
    return false;
}