从ArrayList中过滤数据的最快方法是什么?

6

如何从ArrayList中过滤数据? 例如,我有一个名叫“日期名称”的类。 为了解释,我在下面写了一点代码:

    public class DateAndNames {

        int day;
        int month;
        int year;
        String name;

        public DateAndNames(int day, int month, int year, String name) {
            super();
            this.day = day;
            this.month = month;
            this.year = year;
            this.name = name;
        }
        public int getDay() {
            return day;
        }
...getters and setters...

我这样向数据库中添加数据:

DbHandler hand = new DbHandler(this);
hand.add(new DateAndNames(20, 3, 2008, "Jhon"));
hand.add(new DateAndNames(10, 3, 2008, "Jhon"));
hand.add(new DateAndNames(10, 2, 2004, "Jhon"));
hand.add(new DateAndNames(22, 3, 2008, "Jhon"));

然后我像这样将数据存入ArrayList:
ArrayList<DateAndNames> list = new ArrayList<DateAndNames>();
list = hand.getData();

在将列表传递给BaseAdapter之前,我希望对其进行过滤,所以我现在正在做的是:

//filter by month and year:
public ArrayList<DateAndNames> filterTheList(int month , int year){
    //the data from the database
    list = hand.getData();
    //temp list to store the filtered list
ArrayList<DateAndNames> filteredList = new ArrayList<DateAndNames>();

for (int i = 0; i < list.size(); i++) {
    //check:
    if(list.get(i).getMonth() == month && list.get(i).getYear() == year){

        DateAndNames data = new DateAndNames(
                list.get(i).getDay(), 
                list.get(i).getMonth(), 
                list.get(i).getYear(),
                list.get(i).getName());
        //The data filtered:
        filteredList.add(data);
    }
}
return filteredList;
}

现在,最大的问题是:当我有非常非常大的数据要在for循环中运行,例如300行进行过滤时,应用程序运行非常缓慢!即使使用asyncTask,它仍然工作缓慢!我有点新手,但我希望得到一些好的建议。 编辑:我也尝试了这个...
    public ArrayList<DateAndNames> getData(int month ,int year,String name){
        open();
        ArrayList<DateAndNames> list = new ArrayList<DateAndNames>();

            Cursor c = myDb.query(TABLE_DAY, null, "name= ? and month = ? and year = ?", new String[] {name,month+"",year+""}, null, null, null);
            while (c.moveToNext()) {
            DateAndNames resultData = new DateAndNames(
                    c.getInt(0), //id
                    c.getString(1),//name
                    c.getInt(2), //month
                    c.getInt(3));//year

            list.add(resultData);
            }
close();
return list;
}

但是仍然无法工作...

2
你能否更改你所使用的数据库查询以选择行吗?如果你说“从dates_and_names中选择,其中month = month && year = year”,那么数据将在带入Java之前进行过滤。 - user384842
1
你需要 filteredList 包含新的 DateAndNames 对象,还是 filteredList 中包含指向 list 中相同对象的引用也可以?我不知道你的程序的其余部分是什么,所以我不能回答。但如果列表可以共享引用,则去掉 data 并只说 filteredList.add(list.get(i)) 即可。但是,如果 list.size() 只有 300,我看不出它会花费足够的时间让你注意到。 - ajb
@user384842 谢谢,我想要一个例子。 - Anna
1
无论是300行、3000行,甚至3000行x28列的数据都不算是“非常大”的数据。循环应该几乎是瞬间完成的。你确定时间消耗在这里吗?请注意,初始化“list=new ArrayList<DateAndNames>()”是没有意义的,因为你在下一行就重新分配了它。 - user207421
@Anna,请查看https://dev59.com/WGsz5IYBdhLWcg3w0rVC。 - TooCool
显示剩余8条评论
1个回答

1
我还没有测试过哪种方法是最快的,无论是请求数据库返回筛选列表,还是使用循环自己执行,因为你可以使用多个线程来循环遍历列表,例如考虑使用ExecutorService。不要在单个线程上从1到3000行进行循环,而是将其分成多个组,每个组例如包含500行。然后将每个500行传递给不同的可运行类,并在ExecutorService上运行所有这些类。通过这种方式,过滤时间被CPU核心数除以。另一种方法是在所需列上设置索引,并使用您的参数查询数据库。据我所知,您可以实现的最快方法是上述方法之一,您可以进行实验并找到最佳方法。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接