为什么我的TreeSet不会添加除第一个元素之外的任何内容? [英] Why does my TreeSet not add anything beyond the first element?

查看:99
本文介绍了为什么我的TreeSet不会添加除第一个元素之外的任何内容?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在表单中有几个数组:

I have several arrays in the form:

private static String[] patientNames = { "John Lennon", "Paul McCartney", "George Harrison", "Ringo Starr" };

然后我制作一个这样的TreeSet:

Then I make a TreeSet like this:

TreeSet<Patient> patTreeSet = new TreeSet<Patient>();

其中,Patient是另一个制作Patient对象的类。
然后我遍历我的数组中的每个元素以创建几个患者并将它们添加到我的 patTreeSet ,如下所示:

Where Patient is a different class that makes "Patient" objects. Then I loop through each element in my arrays to create several patients and add them to my patTreeSet like this:

for(int i = 0; i< patientNames.length; i++){
     Date dob = date.getDate("MM/dd/yyyy", patientBirthDates[i]);
     Patient p = new PatientImpl(patientNames[i], patientSSN[i], dob);

     patTreeSet.add(p);
}

但是当我去检查我的 patTreeSet.size ()它只返回1 - 这是为什么?

But when I go to check my patTreeSet.size() it only returns "1" - why is this?

我知道我的对象运行良好,因为当我尝试做同样的事情时事情,但与 ArrayList 相反,一切正常。所以我猜我正在使用TreeSet错误。

I know my objects are working well because when I try to do the same thing but with ArrayList instead, everything works fine. So I'm guessing I'm using the TreeSet wrong.

如果有帮助,Patient有一个名为getFirstName()的方法,当我尝试执行以下操作时:

If it helps, Patient has a method called getFirstName(), and when I try to do the following:

Iterator<Patient> patItr = patTreeSet.iterator();

while(patItr.hasNext()){
    System.out.println(patItr.next().getFirstName());

}

然后只有John打印,显然不应该是这样的...那么,我是否完全滥用TreeSet?

Then only "John" prints, which obviously shouldn't be the case... So, am I totally misusing the TreeSet?

提前感谢您的帮助!

编辑

================ PatientImpl Class ====== ==============

================PatientImpl Class====================

public class PatientImpl implements Patient, Comparable{

    Calendar cal = new GregorianCalendar();
    private String firstName;
    private String lastName;
    private String SSN;
    private Date dob;
    private int age;
    private int thisID;             
    public static int ID = 0;       



    public PatientImpl(String fullName, String SSN, Date dob){

        String[] name = fullName.split(" ");
        firstName = name[0];
        lastName = name[1];

        this.SSN = SSN;

        this.dob = dob;

        thisID = ID += 1;
    }

@Override
    public boolean equals(Object p) {

        //for some reason casting here and reassigning the value of p doesn't take care of the need to cast in the if statement...
        p = (PatientImpl) p;

        Boolean equal = false;
        //make sure p is a patient before we even compare anything
        if (p instanceof Patient) {

            Patient temp = (Patient) p;

            if (this.firstName.equalsIgnoreCase(temp.getFirstName())) {
                if (this.lastName.equalsIgnoreCase(temp.getLastName())) {
                    if (this.SSN.equalsIgnoreCase(temp.getSSN())) {
                        if(this.dob.toString().equalsIgnoreCase(((PatientImpl) p).getDOB().toString())){
                            if(this.getID() == temp.getID()){
                                equal = true;
                            }
                        }
                    }
                }
            }
         }
        return equal;
    }

然后所有的getter都在下面,以及compareTo()方法来自Comparable接口

and then all the getters are below, as well as the compareTo() method from the Comparable interface

推荐答案

如果您将对象放在 TreeSet中 ,你需要在构造函数中提供 Comparator 接口的实现,或者你需要你的对象是一个实现 Comparable的类

If you put your objects in a TreeSet, you need to either provide an implementation of the Comparator interface in the constructor, or you need your objects to be of a class that implements Comparable.

您说过从 Comparable 界面实施 compareTo ,但在你的评论中你说你没有,所以我认为你只需返回0; compareTo 方法?这可以解释你的问题,因为TreeSet会根据 compareTo 方法结果认为你的所有对象都是相同的。

You said you implement compareTo from the Comparable interface, but in your comment you say that you didn't, so am I correct in assuming that you just return 0; in the compareTo method? That would explain your problem, because TreeSet would then think that all your objects are 'the same' based on the compareTo method result.

基本上,在 TreeSet 中,您的对象按排序顺序维护,排序由Comparable / Comparator方法的结果决定。这用于快速查找TreeSet中的重复项,并且具有额外的好处,当您遍历TreeSet时,您将按排序顺序获得结果。

Basically, in a TreeSet, your objects are maintained in a sorted order, and the sorting is determined by the outcome of the Comparable/Comparator method. This is used to quickly find duplicates in a TreeSet and has the added benefit that when you iterate over the TreeSet, you get the results in sorted order.

TreeSet 说:


注意由一组维护的排序(无论是否为显式
比较器提供)必须与equals 一致,如果是
才能正确实现 Set 接口。

最简单的方法是让你的等于方法调用 compareTo 方法并检查结果是否为 0

The easiest way to achieve that is to let your equals method call the compareTo method and check if the result is 0.

给定您的 PatientImpl 类,我假设您希望首先按姓氏对患者进行排序,然后按名字排序,然后再按类别中的其他字段进行排序。

Given your PatientImpl class, I assume that you would want to sort patients first by their last name, then by their first name, and then by the rest of the fields in the class.

您可以像这样实现 compareTo 方法:

You could implement a compareTo method like this:

@Override
public int compareTo(Object o) {
    if (!(o instanceof Patient))
        return -1;
    Patient temp = (Patient) o;
    int r = this.lastName.compareToIgnoreCase(temp.getLastName());
    if (r == 0)
        r = this.firstName.compareToIgnoreCase(temp.getFirstName());
    if (r == 0)
        r = this.SSN.compareToIgnoreCase(temp.getSSN());
    if (r == 0)
        r = this.dob.toString().compareToIgnoreCase(temp.getDOB().toString());
    if (r == 0)
        r = Integer.compare(this.getID(), temp.getID());
    return r;
}

我相信这可以解决你所描述的问题。
我建议你在 TreeSet HashSet 上阅读(Javadoc或书籍)及其重要性等于 compareTo hashCode 方法。
如果你想把你的对象放在一个Set或Map中,你需要知道这些才能正确实现。

I believe that would solve the problem you described. I would advise you to read up (Javadoc or books) on TreeSet and HashSet and the importance of the equals, compareTo and hashCode methods. If you want to put your objects in a Set or a Map, you need to know about these to implement that correctly.

注意
我在等于方法的基础上使用 compareTo 方法。
您通过首先调用toString来比较日期或出生日期。这不是一个很好的方法 - 您可以直接在java.util.Date中使用 equals 方法。在compareTo方法中,问题变得更糟,因为按字母顺序对日期排序时日期无法正确排序。
java.util.Date 还实现了 Comparable ,因此您可以将方法中的比较替换为:

Note I based this compareTo method on your equals method. You were comparing the date-or-birth by first calling toString. That's not a very good way of doing that - you can use the equals method in java.util.Date directly. In a compareTo method the problem gets worse because dates do not sort correctly when you sort them alphabetically. java.util.Date also implements Comparable so you can replace that comparison in the method with:

    if (r == 0)
        r = this.dob.compareTo(temp.getDOB());

此外,如果任何字段可能 null ,你也需要检查它。

In addition, if any of the fields could be null, you need to check for that as well.

这篇关于为什么我的TreeSet不会添加除第一个元素之外的任何内容?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆