2016-04-08 108 views
0

我试图创建一个基本的手机应用程序。我试图(但失败)实现一项功能来查询手机上的现有联系人。我通过创建一个返回包含联系人的对象ArrayList的方法来完成此操作。这应该是通过搜索(使用for循环)来查看是否存在特定的联系人,并将其添加到ArrayList,如果是的话。此后,该方法应该返回一个ArrayList对象,只包含查询的结果。但是,在测试我的代码时,我发现每个联系人都被添加到ArrayList,而不管它是否与查询匹配。下面是我的一些代码片段:将唯一对象添加到ArrayList

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类overrided 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 

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

+2

equals方法,你究竟有没有张贴您正在尝试的代码?它似乎不是,因为在你发布的内容中,当执行'contactsList.add(contact)'时,'contactsList'从未被定义过。因此,这不应该编译成功 –

+0

@VicSeedoubleyew不知道我是如何错过的。我添加了缺少的代码。谢谢 –

+0

欢迎您:) –

回答

2

首先,你的代码不能编译: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()); 
} 
+0

感谢您的评论。但是,尽管我现在知道这是错误的,但我仍然无法理解原始逻辑中的缺陷? –

+0

想象一下,联系人包含Alice,Bob,Carl和Dominic。您正在寻找名为Carl的所有联系人。你开始与爱丽丝联系的循环。你叫findContact(Carl)。它返回true,因为Carl存在于列表中。因此,您将当前联系人Alice添加到列表中。然后循环继续与鲍勃。卡尔是否存在于联系人中。是的,让我们将当前联系人Bob添加到列表中。等等 –

+0

啊,很好的解释。非常感谢,这真的有助于清除它 –

1

最好sulution是使用HashSet

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

无论如何,如果你想使用ArrayL IST:

for (Contact contact : this.contacts) { 
    if(!collection.contains(contact){ 
     collection.add(concat); 
    } 
} 
在两种方案中

必须覆盖Contact.class

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