当前位置: 首页 > 面试题库 >

为什么我的TreeSet不添加除第一个元素之外的任何内容?

楚威
2023-03-14
问题内容

我有几个数组的形式:

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

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

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

其中Patient是制造“
Patient”对象的不同类。然后,我遍历数组中的每个元素以创建多个患者,并将它们添加到我的体内,patTreeSet如下所示:

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”-为什么会这样?

我知道我的对象运行良好,因为当我尝试执行相同的操作但使用ArrayList相反的方法时,一切正常。所以我猜我在使用TreeSet错误。

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

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

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

}

然后只打印“ John”,显然不应该这样……那么,我是否完全滥用了TreeSet?

在此先感谢您的帮助!

*在下面 *编辑

=============== PatientImpl类====================

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;
    }

然后所有吸气剂都在下面,还有Comparable接口中的compareTo()方法


问题答案:

如果将对象放在中TreeSet,则需要Comparator在构造函数中提供接口的实现,或者需要使对象属于实现的类Comparable

您说您是compareToComparable接口实现的,但是在您的评论中您说的不是,所以假设您只是return 0;compareTo方法中,我是否正确?那将解释您的问题,因为TreeSet会根据compareTo方法结果认为您的所有对象都是“相同的” 。

基本上,在中TreeSet,您的对象按已排序的顺序维护,并且排序由Comparable /
Comparator方法的结果确定。这用于在TreeSet中快速查找重复项,并具有额外的好处,即在TreeSet上进行迭代时,您可以按排序顺序获得结果。

的Javadoc TreeSet说:

请注意,如果要正确实现接口,则由一个集合(无论是否提供显式比较器)维护的顺序必须 等于equalsSet

最简单的方法是让您的equals方法调用compareTo方法并检查结果是否为0

对于您的PatientImpl班级,我假设您要首先按患者的姓氏,其名然后对班级中的其他字段进行排序

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

@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;
}

我相信这可以解决您描述的问题。我会建议你阅读了关于(Javadoc中或书籍)TreeSetHashSet和的重要性equalscompareTohashCode方法。如果要将对象放在集合或地图中,则需要了解这些对象才能正确实现。

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

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

另外,如果任何字段可以是null,那么您也需要检查该字段。



 类似资料:
  • 我的表格中有几个数组: 然后我做了一个这样的树集: 其中病人是一个不同的类,它制作“病人”对象。然后,我循环遍历数组中的每个元素,以创建几个患者,并将其添加到我的中,如下所示: 但是当我去检查我的它只返回“1”-这是为什么? 我知道我的对象工作得很好,因为当我尝试做同样的事情,但使用时,一切都很好。所以我猜我用错了树集。 如果有帮助,Patient有一个名为getFirstName()的方法,当我

  • 我正在为C班的期末考试而学习。我们的教授给了我们这个练习题: 解释为什么代码会产生以下输出: 该问题的示例答案是: cout语句只是循环遍历数组元素,其下标由for循环的增量定义。数组初始化不定义元素大小。for循环定义了数组的大小,它碰巧超过了初始化元素的数量,因此最后一个元素默认为零。第一个for循环打印元素0(120),第二个打印元素1(200),第三个循环打印元素2(16),第四个循环打印

  • 我正在编写一个函数,该函数应该删除链表的最后一个元素 这是我对节点的定义 我有一个节点列表1,它为值1、2、3运行了3次insert函数 insert函数如下所示 现在我的delete_last_element函数如下所示 基本上,我的想法是,我会先看看第一个元素是否为空,如果是,我什么也不做,因为没有最后一个元素。然后我将curr设置为head->next以查看列表中的下一个元素,如果它为nul

  • 问题内容: 我有这种方法,可以在登录前检查用户名和密码。现在,我的for循环仅检查第一个项目,它发现第一个项目不满足第一个条件,因此与其去检查第二个项目,它只是中断并返回null。 为什么会这样? 这是我的方法: 问题答案: 因此,请尝试此代码。

  • 我试图返回所有元素,除了中的最后一个元素,如果tuple中只有两个元素,则返回第一个。由于有很多编译时工具,所以应该可以使用双返回类型。以下是我目前掌握的情况: 如果我能以c 17友好的方式来做这件事,那就太好了。我在上述实现中遇到以下错误: /元组。cpp:36:55:错误:包扩展不包含任何未扩展的参数包 返回std::tuple_cat(std::make_tuple(std::get)。。。