【问题标题】:Android : Search from Large ArraylistAndroid:从大数组列表中搜索
【发布时间】:2012-05-10 03:00:25
【问题描述】:

我有大约 29,000 条记录的记录集。我的屏幕包含用于搜索条件的 EditText 框和包含所有 29,000 条记录的列表视图。

通过使用列出的方式进行搜索需要时间,并且不会根据需要提供更少的输出。

我的 EditText 包含

final EditText txtSearchCity = (EditText) findViewById(R.id.edtCity);
        txtSearchCity.addTextChangedListener(new TextWatcher() {
            @Override
            public void afterTextChanged(Editable s) {
            }

            @Override
            public void beforeTextChanged(CharSequence s, int start, int count,
                    int after) {
            }

            @Override
            public void onTextChanged(CharSequence s, int start, int before,
                    int count) {
                aCountryIDTemp.clear();
                aCityStateTemp.clear();

                for (int i = 0; i < aCountryID.size(); i++) {
                    if (aCityState
                            .get(i)
                            .toLowerCase()
                            .contains(
                                    txtSearchCity.getText().toString()
                                            .toLowerCase())) {
                        aCountryIDTemp.add(aCountryID.get(i));
                        aCityStateTemp.add(aCityState.get(i));
                    }
                }

                BindList();
            }
        });
    }

BindList() 方法将 arraylist aCityStateTemp 设置为适配器。 动态搜索和创建新 ArrayList 的任何其他方式。

【问题讨论】:

  • 当编辑文本发生变化时,最好使用数据库并执行 LIKE 查询。
  • @Dharmendra 正在做同样的事情而不是这样做.. 但需要同样的时间..
  • @Vishal Khakhkhar 我正在使用自定义键盘输入edittext,但我在更快地按下按钮时遇到延迟我有1000多条记录。我如何改进请帮助

标签: android arrays arraylist


【解决方案1】:

我会坚持使用Lambdaj 库,它主要用于您希望限制循环以对集合进行排序和过滤的情况。

这是一个使用 lambdaj 过滤 ArrayList 的小例子。

ArrayList<String> sortedArrayList = select(arrList, having(on(String.class),
                                                   Matchers.containsString("a");

这将返回一个完整过滤的ArrayList,您要使用它来填充您的ListView

您还可以filter 自定义类 - Java: What is the best way to filter a Collection?

更新:

以上解决方案是case-sensitive,因此您可以添加Multiple Matchers

这样可以加Multiple Matchers

ArrayList<String> sortedArrayList = select(arrList, having(on(String.class),
   (Matchers.anyOf(Matchers.containsString("a"),Matchers.containsString("A")))));

更新:

更好的方法是使用filter(Matcher&lt;?&gt; matcher, T...array)

你可以这样做,

ArrayList<String> sortedArrayList = filter(Matchers.anyOf(
           Matchers.containsString("a"),Matchers.containsString("A")), arrList);

另外,如果您有兴趣使用lambdaj 的某些方法/功能,您可以提取源代码并使其正常工作。我正在为filter()添加相同的内容

您只需下载hamcrest-all-1.0.jar(63 kb) 并添加以下代码即可使filter() 正常工作

public static <T> List<T> filter(Matcher<?> matcher, Iterable<T> iterable) {
    if (iterable == null)
        return new LinkedList<T>();
    else{
        List<T> collected = new LinkedList<T>();
        Iterator<T> iterator = iterable.iterator();
        if (iterator == null)
            return collected;
        while (iterator.hasNext()) {
            T item = iterator.next();
            if (matcher.matches(item))
                collected.add(item);
        }
        return collected;
    }
}

因此,您可以从lambdaj 源中挑选出最少的并集成到您的源中。

【讨论】:

  • 一流图书馆 +1 Mr Poptani。
  • 一个非常好的库,但遗憾的是它不适用于 Android。在我放弃之前,我看到了以下链接。尽管如此,如果需要,我会将它作为非 Android 项目的一个选项。 stackoverflow.com/a/16528057/1276636
  • 这个库的匹配器是什么?我在 Matchers 函数中发现错误。请解释一下
  • public static List filter(Matcher> matcher, Iterable iterable) { if (iterable == null) return new LinkedList(); else{ List 收集 = new LinkedList();迭代器 迭代器 = iterable.iterator(); if (iterator == null) 返回收集; while (iterator.hasNext()) { T item = iterator.next(); if (matcher.matches(item)) collect.add(item); } 返回收集; } }
  • ArrayList sortedArrayList = (ArrayList) filter(Matchers.anyOf( Matchers.containsString(searchText),Matchers.containsString(searchText.toUpperCase())), productList);跨度>
【解决方案2】:

您可以将所有数据存储在 sqlite 数据库中,并使用类似查询检索搜索到的项目。

【讨论】:

  • 我之前也是这样做的..但它需要相同的时间..所以使用了这种方法。
【解决方案3】:

我假设您在初始化 Adapter 时已将 aCityStateTemp 作为 ArrayList 传递给您 Adapter

现在更改aCityStateTemp 的内容后,您只需调用adapter.notifyDataSetChanged()。您不需要将aCityStateTemp 设置为新的ArrayList 适配器。

【讨论】:

  • Adil.. 我没有按照你建议的方式做,但现在我尝试改变你建议的方式。事实上 adapter.notifyDataSetChanged() 是刷新适配器的好方法,所以就这样做了。但要花同样的时间。
【解决方案4】:

您可以使用 HashSet 或 LinkedHashSet(保持插入顺序)进行快速搜索。 使用该类的 contains() 方法。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-02-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-04-13
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多