使用大数组列表加速自动完成算法 [英] Speeding up AutoComplete algorithm with a big Array List

查看:74
本文介绍了使用大数组列表加速自动完成算法的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用Android应用程序上的 InstantSearch功能,而我想要实现的结果如下图所示.

I'm dealing with the InstantSearch feature on my Android App and the result I'd like to achieve is the one in the following picture.

除一件事外,其他所有东西都可以正常工作.我正在使用的ArrayList是BIG(包含近40万个单词).因此,我在ListView上显示结果时遇到性能问题(它滞后很多).

Everything works properly except for one thing. The ArrayList I'm using is BIG (it contains almost 400k words). Hence, I have performance issues while showing my results on the ListView (it lags a lot).

我很确定这是由我的单词表的长度引起的,因为减少单词的数量,一切都像黄油一样光滑.

I'm pretty sure it's caused by the length of my Wordlist because, reducing its number of words, everything is smooth as butter.

这是适配器类中的过滤代码:

private class SearchResultsFilter extends Filter {

    @Override
    protected FilterResults performFiltering(CharSequence constraint) {

        FilterResults filterResults = new FilterResults();

        ArrayList<String> found = new ArrayList<>();
        if (constraint != null) {
            for (String word : MainActivity.WordList) {
                if (word.startsWith(constraint.toString().toLowerCase())) {
                    found.add(word);
                }
            }
        }

        filteredList = found;
        filterResults.values = found;
        filterResults.count = found.size();

        return filterResults;
    }

    @Override
    protected void publishResults(CharSequence constraint, FilterResults filterResults) {
        if (filterResults.count > 0) {
            Log.println(Log.INFO, "Results", "FOUND");
            results.clear();
            results.addAll((ArrayList<String>) filterResults.values);
            notifyDataSetChanged();
        } else {
            Log.println(Log.INFO, "Results", "-");
            results.clear();
            notifyDataSetInvalidated();
        }

    }
}

这就是我在 MainActivity 中加载ArrayList的方式:

That's how I load my ArrayList in my MainActivity:

public static void loadDictionary(Activity activity) {
        //loading wordslist from file.
        BufferedReader line_reader = new BufferedReader(new InputStreamReader(activity.getResources().openRawResource(R.raw.wordlist)));
        String line;
        try {
            while ((line = line_reader.readLine()) != null) {
                WordList.add(line);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        Collections.sort(WordList);

谢谢大家

祝你有美好的一天.

推荐答案

我是Cesarsk项目的合作者,我注意到我们的问题是 performFiltering 方法.我们使用的Wordlist中包含394.000+个元素,并且每次用户在SearchBar的EditText中键入一个字母时,即使每个迭代中都应排除某些元素,performFiltering方法也会检查所有元素.因此,我实现了一种简单的方法将列表拆分为不同的子列表.每个列表仅包含以字母中的单个字母开头的单词.

I'm a collaborator in Cesarsk's project, I noticed that our problem was the performFiltering method. The Wordlist we used, had 394.000+ elements in it and the performFiltering method checked all of them each time the user typed a letter in the EditText of the SearchBar even if it should have excluded some on each iteration. So I implemented a simple way to split the list in different sublists. Each list contains only word starting with a single letter from the alphabet.

含义:

  • 列表1仅包含以字母" a "开头的单词
  • 列表2仅包含以字母" b "

  • List 1 contains only words starting with the letter "a"
  • List 2 contains only words starting with the letter "b"

依此类推...

然后,我将所有列表放入 HashMap 中,其中 key =字母.这样做,现在我们只能选择与用户键入的第一个字母匹配的子列表,并且循环检查的单词要少得多,从而立即产生结果.

Then I put all the lists in an HashMap with key = letter of the alphabet. Doing this, now We are able to select only the sublist matching the first letter the user typed, and the loop checks a lot less words, generating results instantly.

以下是一些代码:

@Override
    protected FilterResults performFiltering(CharSequence constraint) {

        FilterResults filterResults = new FilterResults();

        ArrayList<Pair<String, String>> temp_list = null;
        ArrayList<Pair<String, String>> found = new ArrayList<>();

        if (constraint != null) {
            if (!(constraint.toString().isEmpty())) {
                temp_list = MainActivity.Wordlists_Map.get(constraint.toString().substring(0,1).toLowerCase());

                if(temp_list != null){
                    for(Pair<String, String> element : temp_list){
                        if(element.first.startsWith(constraint.toString().toLowerCase())){
                            found.add(element);
                        }
                    }
                }
            }
        }

        filterResults.values = found;
        filterResults.count = found.size();

        return filterResults;
    }

这篇关于使用大数组列表加速自动完成算法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆