Slow search ignoring accents

Asked

Viewed 400 times

2

I have a list of objects and I’m doing a title search.

I use the Normalize to make the comparison by ignoring accents:

public static boolean containsIgnoreCaseAndAccents(String haystack, String needle) {
    final String hsToCompare = removeAccents(haystack).toLowerCase();
    final String nToCompare = removeAccents(needle).toLowerCase();

    return hsToCompare.contains(nToCompare);
}

public static String removeAccents(String string) {
    return ACCENTS_PATTERN.matcher(Normalizer.normalize(string, Normalizer.Form.NFD)).replaceAll("");
}

And the search:

for(Object o : allObjects){

            if(o.getTitle()!=null && containsIgnoreCaseAndAccents(o.getTitle(), text)) {
                searchObjects.add(o);
            }
}

The text I take from mine Edittext. It works, but there is one delay in this comparison, and the search is slightly stalled, giving a delay by typing each letter.

Is there any way to make this comparison faster?

2 answers

3

For each "title" you check you are always removing the accents from the text to compare.

Remove only the accents from the text once and use it in each comparison with the "title"

Use a class to make comparisons:

public classe IgnoreCaseAndAccentsComparator{

    private String text;  

    IgnoreCaseAndAccentsComparator(String text){

        this.text = removeAccents(text).toLowerCase();
    }

    public boolean contains(String text){

        this.text.contains(removeAccents(text).toLowerCase());
    }

    //Se quiser pode adicionar outros métodos de comparação

    public static String removeAccents(String string) {
        return ACCENTS_PATTERN.matcher(Normalizer.normalize(string, Normalizer.Form.NFD)).replaceAll("");
    }
}

Use like this:

IgnoreCaseAndAccentsComparator comparator = new IgnoreCaseAndAccentsComparator(text);

for(Object o : allObjects){

    if(o.getTitle()!=null && comparator.contains(o.getTitle())) {
        searchObjects.add(o);
    }
}

If the search is done while the text is typed the performance can be improved by using a "delay" between each call to the method so that it is not called by each input letter but only after there is a pause in the introduction.

Note: I just tried to optimize your code without questioning how the accents are removed, which can possibly also be optimized.

  • 1

    I tested it. It got slightly faster, but the dalay is still present. I solved the problem otherwise, I’ll submit the answer, maybe you can make improvements comments.

0

My problem was having to do the research while the text was typed. As it was a typed search, there are not many accented letters options. I used this answer (/a/2626/1385) as basis and I made my method to replace the accented strings.

Thus remaining:

public static String removeAccent(String lowerCaseString)
{
    String withAccent = "äáâàãéêëèíîïìöóôòõüúûùç";
    String withoutAccent = "aaaaaeeeeiiiiooooouuuuc";

    for (int i = 0; i < withAccent.length(); i++)
    {
        lowerCaseString = lowerCaseString.replace(withAccent.charAt(i), withoutAccent.charAt(i));
    }
    return lowerCaseString;
}

The performance was good and works for the keyboard accents of Android, until the searches will be done in English.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.