【问题标题】:Adding unique objects to ArrayList向 ArrayList 添加唯一对象
【发布时间】:2016-04-08 21:00:46
【问题描述】:

我正在尝试创建一个基本的手机应用程序。我正在尝试(但失败)实现一项功能来查询手机上的现有联系人。我通过创建一个返回包含联系人的ArrayList 对象的方法来做到这一点。这应该通过搜索(使用for 循环)来查看特定联系人是否存在,如果存在则将其添加到ArrayList。此后,该方法应返回一个ArrayList 对象,该对象只包含查询结果。但是,在测试我的代码时,我发现每个联系人都添加到ArrayList,无论它是否与查询匹配。以下是我的代码的一些 sn-ps:

Phone.java

private ArrayList<Contact> contacts;

public Phone() {
    this.contacts = new ArrayList<>();
}

public ArrayList<Contact> queryContacts(String contactName) {
       ArrayList<Contact> contactsList = new ArrayList<>();

        for (Contact contact : this.contacts) {
            if (this.findContact(contactName)) 
                contactsList.add(contact);
        }
        return contactsList;
    }

    private boolean findContact(String contactName) {
            for (Contact contact : this.contacts) {
                if (contact.getName().equals(contactName))
                    return true;
            }
            return false;
}

测试我的代码 (Main.java)

public static void main(String[] args) {
        char c= 'A';

        for (int i = 0; i < 10; i++) {
            //Create contacts with unique data
            phone.addContact(Contact.createContact("Contact"+c++, "07"+i));
        }

        System.out.println(phone.queryContacts("VoidContact")); //Dubious entry
        System.out.println(phone.queryContacts("ContactB")); //This entry exists
    }

没错,在使用“VoidContact”参数调用phone.queryContacts() 方法时,我没有收到任何输出。但是,在使用合法参数“ContactB”调用它时,而不是只接收一个联系人,我得到以下输出(请注意,我在 Contact 类中覆盖了 Object.toString()) :

Name: 'ContactA' Number: 070
Name: 'ContactB' Number: 071
Name: 'ContactC' Number: 072
Name: 'ContactD' Number: 073
Name: 'ContactE' Number: 074
Name: 'ContactF' Number: 075
Name: 'ContactG' Number: 076
Name: 'ContactH' Number: 077
Name: 'ContactI' Number: 078
Name: 'ContactJ' Number: 079

我的问题;为什么根据输入的参数输出每个联系人而不是唯一联系人?非常感谢您的回复。

【问题讨论】:

  • 您是否准确地发布了您正在尝试的代码?似乎不是,因为在您发布的内容中,在执行contactsList.add(contact) 时,从未定义过contactsList。因此这不应该编译成功
  • @VicSeedoubleyew 不知道我是怎么错过的。我添加了缺少的代码。谢谢

标签: java object arraylist


【解决方案1】:

首先,您的代码无法编译:contactsList 变量未在任何地方定义。

第二,你的逻辑有缺陷:

    for (Contact contact : this.contacts) {
        if (this.findContact(contactName)) 
            contactsList.add(contact);
    }
    return contactsList;

让我们翻译成英文:对于每个联系人,如果列表包含contactName,则将联系人添加到列表中。因此,如果列表中包含联系人姓名,则将所有联系人添加到列表中,否则不添加任何联系人。

您真正想要的是一种在列表中找到具有给定名称的联系人的方法:

public List<Contact> queryContacts(String contactName) {
    List<Contact> contactsList = new ArrayList<>();
    for (Contact contact : this.contacts) {
        if (contact.equals(contactName)) { 
            contactsList.add(contact);
        }
    }
    return contactsList;
}

或者,使用 Java 8:

public List<Contact> queryContacts(String contactName) {
    return contacts.stream()
                   .filter(contact -> contact.getName().equals(contactName))
                   .collect(Collectors.toList());
}

【讨论】:

  • 感谢您的评论。然而,虽然我现在知道错了,但我还是没能理解原来逻辑的缺陷?
  • 想象联系人包含 Alice、Bob、Carl 和 Dominic。您正在查找所有名为 Carl 的联系人。您从联系人 Alice 开始您的循环。然后你调用 findContact(Carl)。它返回 true,因为 Carl 存在于列表中。因此,您将当前联系人 Alice 添加到列表中。然后循环继续 Bob。卡尔是否存在于联系人中。是的,所以让我们将当前联系人 Bob 添加到列表中。等等等等。
  • 啊,很好的解释。非常感谢,这确实有助于清除它
【解决方案2】:

最好的解决方案是使用 HashSet

Set<Contact> collection=new HashSet<Contact>();
//...
for (Contact contact : this.contacts) {
   collection.add(concat);
}

无论如何,如果你想使用 ArrayList:

for (Contact contact : this.contacts) {
   if(!collection.contains(contact){
      collection.add(concat);
   }
}

在这两种解决方案中,您都必须覆盖 Contact.class 中的 equals 方法

public boolean equals(Object o){
   if(o == null) return false;
   if(o instanceof Contact){
      Contact c=(Contact)o;
      return c.name.equals(this.name);
   }
   return false;
}

【讨论】:

    猜你喜欢
    • 2012-03-16
    • 1970-01-01
    • 1970-01-01
    • 2014-02-03
    • 1970-01-01
    • 2022-12-17
    • 1970-01-01
    • 2016-06-28
    • 1970-01-01
    相关资源
    最近更新 更多