简体   繁体   English

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

[英]how to make search faster from contactList for given string

I have ContactList which contains contacts with firstName and lastName. 我有ContactList,其中包含具有firstName和lastName的联系人。 I want to perform search by FirstName or lastName. 我想按名字或姓氏执行搜索。

I have already written code which works fine but I want to improve search in terms of speed and memory. 我已经编写了可以正常工作的代码,但是我想提高速度和内存方面的搜索。

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

Please suggest how to improve performance in above code. 请在上面的代码中建议如何提高性能。

You could use a java.util.HashMap , to store a lookup table for Contacts for search terms. 您可以使用java.util.HashMap来存储联系人搜索字词的查找表。

The idea is to pre-populate the lookup table with likely search terms (eg the first name or the first three letters of the name). 想法是用可能的搜索词(例如名称的名字或前三个字母)预填充查找表。 If your lookup doesn't return any matches you can always perform a full search. 如果您的查询未返回任何匹配项,则您始终可以执行完整搜索。 If you want more powerful searching you could look at something like Apache Lucene . 如果您想进行更强大的搜索,可以看看Apache Lucene之类的东西。

Eg 例如

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

Then you'd start by looking up the search term in the map. 然后,您将首先在地图上查找搜索字词。 This would narrow down the possibilities to a small set which you can iterate over using the same method you use above. 这会将可能性缩小到一小组,您可以使用与上面相同的方法进行迭代。

You might also look at the Multimap from Guava, which provides the same capability more elegantly. 您可能还会看到Guava的Multimap ,它更优雅地提供了相同的功能。


By the way (on an unrelated note) when you override the compareTo() method it is good practice to also override equals() so that (x.compareTo(y)==0) == (x.equals(y)) . 顺便说一句(不相关的注释),当您重写compareTo()方法时,最好也重写equals()以便(x.compareTo(y)==0) == (x.equals(y))

And when you override equals() you will also need to override hashCode() ! 当您覆盖equals()您还需要覆盖hashCode()

I dont have predefined searchTerms, my requirement is like User entered contacts like "Manoj Pathak", "Manoj". 我没有预定义的searchTerm,我的要求就像用户输入的联系人一样,例如“ Manoj Pathak”,“ Manoj”。 If user type "Man" and hit search then result will be Manoj Pathak Manoj If user type "Manoj" and hit search then result will be Manoj (exact match) Manoj Pathak" 如果用户键入“ Man”并命中搜索,则结果将为Manoj Pathak Manoj如果用户键入“ Manoj”并命中搜索,则结果将为Manoj(完全匹配)Manoj Pathak”

In this case I will suggest you implement Longest prefix matching – A Trie based solution in Java which internally will use HashMap. 在这种情况下,我建议您实现最长前缀匹配– Java基于Trie的解决方案 ,内部将使用HashMap。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM