2013-11-27 3 views
0

У меня есть ArrayList, который содержит элементы (поля - это имя и тип). Есть только два разных возможных типа («edu» и «ent»), которые я хочу, чтобы каждый отображался в своем собственном списке.Фильтр ArrayList и удаление ненужных элементов

Моя идея состояла в том, чтобы создать два новых 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)); 

Есть 10 элементов в ArrayList, 5 каждого типа.

Проблема в том, что в конце обоих списков есть 4 одинаковых элемента, отображаемых со смешанными типами.

Любая идея, что я сделал неправильно?

+0

Вы исследовали [http://stackoverflow.com/questions/2250770/how-to-refresh-android-listview][1] ?? [1]: http://stackoverflow.com/questions/2250770/how-to-refresh-android-listview – Elorry

+0

Я не пытаюсь обновить ListView. Если я проверю, что происходит в циклах, я вижу, что по какой-то неизвестной причине ArrayList не фильтруется правильно. – Soriyyx

ответ

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

Да, назначение просто скопирует значение data_ent (что является ссылкой) на data_edu. Они оба будут ссылаться на один и тот же объект. Так что любые изменения, внесенные в любом списке, одни и те же изменения будут отражены в другом списке, а

Это вы должны сделать: -

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

или использовать addAll() функцию списка массива.

1

Как только вы удаляете предмет из своего ArrayList, все предметы сменятся. Вы можете либо добавить в i-- после remove, или использовать итератор:

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

В вашей для для петель, вы можете пропустить пункты. Допустим, ваш список что-то вроде этого:

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

Ваш индексная переменная будет i = 0. list[i] == "edu" затем удалить его, но тогда ваш список становится:

list = {edu, ent, ent, edu} 

Но переменная индекс получает приращение и затем равен 1. и list[1] = "ent". Поскольку вы undersand не обрабатываете первый элемент списка. Вы пропустили индексы.

Надеюсь, это ясно.

Если у вас есть Викисклада коллекции доступны в вашем проекте, вы можете также использовать метод фильтрации на CollectionUtils:

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

Рахул правильно относительно ссылок списка, но есть еще одна проблема, как хорошо.

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), то второе образование становится новым индексом 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(); 
    } 
} 
1
  1. Ваш удалить цикл неправильно. Вы можете использовать это: for (int i = data_end.size - 1, i> = 0, i--)
  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; 
    } 
    

Используйте функцию фильтра:

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)); 
0

Рассмотрите возможность использования библиотеки Guava для коллекций фильтрации: http://www.motta-droid.com/2013/12/collections-performance-tests-in.html

В приведенном выше примере фильтр возвращает новый фильтрованного коллекции не влияют на сбор источников. Возможно, не стоит добавлять библиотеку для одной маленькой задачи, и если коллекции не содержат много предметов, но это хороший инструмент для ознакомления.

Смежные вопросы