我有一个包含元素的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个相同的项目显示为混合类型。
知道我做错了吗?
答案 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 = 0
。 list[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)
解决方案非常简单。您的代码首先是过滤函数
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;
}
使用过滤功能:
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
在上面的示例中,过滤器返回新过滤的集合不会影响源集合。也许没有时间为一个小任务添加一个库,如果集合中没有太多项目,但它是一个熟悉的好工具。