如何从contactList获得更快的搜索给定字符串

时间:2016-06-26 09:05:11

标签: java sorting search collections

我有ContactList,其中包含firstName和lastName的联系人。我想通过FirstName或lastName执行搜索。

我已经编写了可以正常运行的代码,但我希望在速度和内存方面改进搜索。

public class Contact implements Comparable<Contact> {

    private String firstName;
    private String lastName;
    private String name;

    public Contact(String name) {

        this.name = name;
        if (name.contains(" ")) {
            this.firstName = name.split("\\s+")[0];
            this.lastName = name.split("\\s+")[1];
        } else {
            this.firstName = name;
            this.lastName = "";
        }
    }

    public String getFirstName() {
        return firstName;
    }

    public String getLastName() {
        return lastName;
    }

    public String getName() {
        return name;
    }

    @Override
    public String toString() {
        return "Contact{" + name + '}';
    }

    @Override
    public int compareTo(Contact contact) {
        System.out.println("in compareto");
        return this.name.compareToIgnoreCase(contact.getName());
    }
@Override
public int hashCode() {
    return (firstName.hashCode() * (lastName != null ? lastName.hashCode() : 0));
}

@Override
public boolean equals(Object obj) {
    if(obj == null)
        return false;
    if(!(obj instanceof Contact)) 
        return false;

    Contact other = (Contact) obj;
    if(! this.name.equalsIgnoreCase(other.name)) return false;

    return true;
}
  }

public class ContactService {

    private Set<Contact> contacts;

    public ContactService() {
        this.contacts =  new TreeSet<>();
    }

    public void addContact(String name) {
        Contact contact = new Contact(name);
        contacts.add(contact);
    }

    public void searchContact(String searchStr) {
        System.out.println(contacts);
        for (Contact contact : contacts) {
            if (contact.getName().equalsIgnoreCase(searchStr)||(searchStr.contains(" ") && contact.getName().contains(searchStr))) {
                System.out.println(contact.getName());
            } else if (contact.getFirstName().toLowerCase().startsWith(searchStr) || contact.getLastName().toLowerCase().startsWith(searchStr)) {
                System.out.println(contact.getName());
            }
        }
    }
}

请在上面的代码中建议如何提高效果。

2 个答案:

答案 0 :(得分:1)

您可以使用java.util.HashMap来存储搜索字词的“联系人”查找表。

这个想法是用可能的搜索词(例如名字的名字或前三个字母)预填充查找表。如果您的查找未返回任何匹配项,则您始终可以执行完整搜索。如果您想要更强大的搜索功能,可以查看类似Apache Lucene的内容。

E.g。

Map<String, Set<Contact>> contactLookup = new HashMap<>();

然后,您首先在地图中查找搜索词。这样可以缩小使用上面使用的相同方法迭代的小集合的可能性。

您还可以查看来自Guava的Multimap,它可以更优雅地提供相同的功能。

顺便说一句(在不相关的说明中)当您覆盖compareTo()方法时,最好还是覆盖equals()以便 (x.compareTo(y)==0) == (x.equals(y))

当您覆盖equals()时,您还需要覆盖hashCode()

答案 1 :(得分:0)

  

我没有预定义的searchTerms,我的要求就像User   进入了像“Manoj Pathak”,“Manoj”这样的联系人。如果用户输入“Man”和   点击搜索然后结果将是Manoj Pathak Manoj如果用户输入“Manoj”   并点击搜索然后结果将是Manoj(完全匹配)Manoj Pathak“

在这种情况下,我建议你实现最长前缀匹配 - 基于Trie的Java解决方案,内部将使用HashMap。