过滤ArrayList并删除不需要的元素

时间:2013-11-27 16:24:05

标签: java android

我有一个包含元素的ArrayList(字段是名称和类型)。只有两种不同的可能类型(“edu”和“ent”),我希望每种类型都显示在自己的列表视图中。

我的想法是创建两个具有相同数据的新ArrayLists,然后遍历每个并过滤掉不需要的元素,如下所示:

ListView listView_ent = (ListView) findViewById(R.id.popular_apps_list_ent);
ArrayList<DataHolder> data_ent = data;
for (int i = 0; i < data_ent.size(); i++) {
    if(data_ent.get(i).getType().equals("edu")){
        data_ent.remove(i);
    }
}
listView_ent.setAdapter(new AppsAdapter(this, data_ent));

ListView listView_edu = (ListView) findViewById(R.id.popular_apps_list_edu);
ArrayList<DataHolder> data_edu = data;
for (int i = 0; i < data_edu.size(); i++) {
    if(data_edu.get(i).getType().equals("ent")){
        data_edu.remove(i);
    }
}
listView_edu.setAdapter(new AppsAdapter(this, data_edu));

ArrayList中有10个元素,每种类型有5个元素。

问题是,在两个列表视图的最后,有4个相同的项目显示为混合类型。

知道我做错了吗?

7 个答案:

答案 0 :(得分:3)

1)复制数据

2)不要使用i迭代并删除;使用迭代器(删除方法:http://docs.oracle.com/javase/7/docs/api/java/util/Iterator.html#remove())或从列表末尾开始

类似的东西:

ListView listView_ent = (ListView) findViewById(R.id.popular_apps_list_ent);
ArrayList<DataHolder> data_ent = new ArrayList( data);
for (int i = data_ent.size()-1; i >= 0; i--) {
    if(data_ent.get(i).getType().equals("edu")){
        data_ent.remove(i);
    }
}
listView_ent.setAdapter(new AppsAdapter(this, data_ent));

ListView listView_edu = (ListView) findViewById(R.id.popular_apps_list_edu);
ArrayList<DataHolder> data_edu = = new ArrayList( data);
for (int i = data_edu.size()-1; i >= 0 ; i--) {
    if(data_edu.get(i).getType().equals("ent")){
        data_edu.remove(i);
    }
}
listView_edu.setAdapter(new AppsAdapter(this, data_edu));

答案 1 :(得分:1)

是的,分配只会将data_ent(这是一个参考)的值复制到data_edu。它们都会引用同一个对象。因此,无论您在任何一个列表中进行任何更改,相同的更改也会反映在另一个列表中

这是你应该做的: -

List<Integer> data_edu = new ArrayList<Integer>(data_ent);

或使用数组列表的addAll()函数。

答案 2 :(得分:1)

ArrayList中删除某个项目后,所有内容都会向下移动。您可以在i--之后添加remove,也可以使用迭代器:

Iterator<DataHolder> i = data_edu.iterator();
while (i.hasNext()) {
    DataHolder d = i.next();
    if (d.getType().equals(...) {
        i.remove();
    }
}

答案 3 :(得分:1)

在for for for循环中,您可能正在跳过项目。假设您的列表是这样的:

list = {edu, edu, ent, ent, edu}

您的索引变量为i = 0list[i] == "edu"然后删除它,但随后您的列表变为:

list = {edu, ent, ent, edu}

但是你的索引变量会增加,然后等于1.和list[1] = "ent"。如你所示,你没有处理列表的第一个元素。你跳过了索引。

希望这很清楚。

如果您的项目中有公共收藏品,您也可以使用CollectionUtils上的过滤方法:

    CollectionUtils.filter(your_list, new Predicate() {
        @Override
        public boolean evaluate(Object obj) {
             return !((DataHolder) obj).getType().equals("edu");
        }
    });

答案 4 :(得分:1)

Rahul关于列表引用是正确的,但您还有另一个问题。

ListView listView_ent = (ListView) findViewById(R.id.popular_apps_list_ent);
ArrayList<DataHolder> data_ent = data;
for (int i = 0; i < data_ent.size(); i++) {
    if(data_ent.get(i).getType().equals("edu")){
        data_ent.remove(i);
    }
}

问题在于,当您删除时,您会错误地编写索引。你实际上是在跳过物品。考虑

{"edu", "edu", "ent"}

取出第一个项目(索引0)后,第二个edu成为新索引0,但您继续前进并检查索引1.

尝试使用ListIterator http://docs.oracle.com/javase/6/docs/api/java/util/ListIterator.html

提示:

ListIterator<DataHolder> entDataIterator = data_ent.listIterator();
while(entDataIterator.hasNext(){
    if(/*whatever*/){
        entDataIterator.remove();
    }
}

答案 5 :(得分:1)

  1. 你的删除循环错误。您可以使用:for(int i = data_end.size - 1,i&gt; = 0,i - )
  2. 稍后考虑功能扩展?使用2种以上?
  3. 解决方案非常简单。您的代码首先是过滤函数

    public List<DataHolder> filterBy(List<DataHolder> list, String type) {
        List<DataHolder> l = new ArrayList<>();
        for ( DataHolder h : list) {
            if (h.getType().equals(type)) {
                l.add(h);
            }
        }
        return l;
    }
    
  4. 使用过滤功能:

        List<DataHolder> eduList = filterBy(data, "edu");
        listView_edu.setAdapter(new AppsAdapter(this, eduList));
    
        List<DataHolder> entList = filterBy(data, "ent");
        listView_ent.setAdapter(new AppsAdapter(this, entList));
    

答案 6 :(得分:0)

考虑使用Guava库过滤集合: http://www.motta-droid.com/2013/12/collections-performance-tests-in.html

在上面的示例中,过滤器返回新过滤的集合不会影响源集合。也许没有时间为一个小任务添加一个库,如果集合中没有太多项目,但它是一个熟悉的好工具。