4

I have a generic arraylist of an object here I want to remove certain elements, The problem is when I iterate the list with for loop, I can't do a simple sequence of remove()'s because the elements are shifted after each removal.

Thanks

Korhan Ozturk
  • 11,148
  • 6
  • 36
  • 49
Rakshi
  • 6,796
  • 3
  • 25
  • 46

6 Answers6

17

Use Iterator to remove element

Like

Iterator itr = list.iterator();
String strElement = "";
while (itr.hasNext()) {
    strElement = (String) itr.next();
    if (strElement.equals("2")) {
        itr.remove();
    }
}
Community
  • 1
  • 1
Samir Mangroliya
  • 39,918
  • 16
  • 117
  • 134
  • Changed your link to point to the Android Iterator. Before it was pointing to a previous Java version. Feel free to revert it if you feel like. – npinti Jul 11 '12 at 09:06
  • if i have to remove the 2nd and the 4th item in the list there will be a problem. as the 2nd item is deleted there will be a shift – Rakshi Jul 11 '12 at 09:06
  • 1
    @Rakshi: If you know which elements you want to delete, you can do without the for loop. – npinti Jul 11 '12 at 09:09
  • if there are 5 items in my list, i have to delete the 2nd and the 5th item, if i remove the 2nd item first then the list will have only 4 items and there will be an exception when i try to remove the 5th – Rakshi Jul 11 '12 at 09:12
  • 1
    With an iterator you can handle always the element which comes to order, not a specified index. So, you should not be troubled with the above matter. – arjacsoh Jul 11 '12 at 09:15
2

You can iterate the list this way ...

public void clean(List<Kopek> kopeks) {
  for(Kopek kopek : kopeks) {
    if (kopek.isDirty())
      kopeks.remove(kopek);
  }
}

Which is equiv to ...

public void clean1(List<Kopek> kopeks) {
  Iterator<Kopek> kopekIter = kopeks.iterator();

  while (kopekIter.hasNext()) {
    Kopek kopek = kopekIter.next();
    if (kopek.isDirty())
      kopeks.remove(kopek);
  }
}

Don't do this ... (due to the reason you have already observed.)

public void clean(List<Kopek> kopeks) {
  for(int i=0; i<kopeks.size(); i++) {
    Kopek kopek = kopeks.get(i);
    if (kopek.isDirty())
      kopeks.remove(i);
  }
}

However, I believe removal by index rather than by object is more efficient. Removal by object is not efficient because the list is in most cases not a hashed list.

kopeks.remove(kopek);

vs

kopeks.remove(i);

To achieve positional remove, by treating a moving target appropriately ...

public void clean(List<Kopek> kopeks) {
  int i=0;
  while(i<kopeks.size()) {
    Kopek kopek = kopeks.get(i);
    if (kopek.isDirty()) // no need to increment.
      kopeks.remove(i);
    else
      i++;
  }
}
Blessed Geek
  • 21,058
  • 23
  • 106
  • 176
  • Thanks for the effort.. but the solution list.remove(object); even dosent help it creates the same exception.. its better use iterator or check the solution without using iterators below – Rakshi Jul 11 '12 at 09:45
1

If you have the objects that you want to remove from your ArrayList<T> you can use :

mArrayList.remove(object);

or you can use an Iterator to remove your objects:

while(iterator.hasNext()){
    if(iterator.next() == some condition for removal){
        iterator.remove();
    }
}
Ovidiu Latcu
  • 71,607
  • 15
  • 76
  • 84
  • The problem is when i remove any of the item in the list there will be a shift and it generates an exception – Rakshi Jul 11 '12 at 09:15
1

You could iterate backwards and remove as you go through the ArrayList. This has the advantage of subsequent elements not needing to shift and is easier to program than moving forwards.

   List<String> arr = new ArrayList<String>();
   ListIterator<String> li = arr.listIterator(arr.size());

    // Iterate in reverse.
    while(li.hasPrevious()) {

        String str=li.previous();
        if(str.equals("A"))
        {
            li.remove();
        }
    }
amicngh
  • 7,831
  • 3
  • 35
  • 54
0

Create a separate ArrayList of Index of the data to be removed from the original ArrayList, then remove those elements by looping over it with for loop.

ArrayList<Myobj> arr = new ArrayList<Myobj>();

for (Myobj o : arr){

  arr.remove(arr.indexOf(o));

 }
Kumar Vivek Mitra
  • 33,294
  • 6
  • 48
  • 75
  • The problem is when i remove any of the item in the list there will be a shift and it generates an exception – Rakshi Jul 11 '12 at 09:16
  • what you want to do actually, you want the data from the removed data from the ArrayList or want the index of the newly formed ArrayList after removing the data. – Kumar Vivek Mitra Jul 11 '12 at 09:28
  • i need to remove random objects from the list. like if there are 5 items in the list i want to remove the 2nd and 4th objects.. you can find the solution below. Thanks for the intrest – Rakshi Jul 11 '12 at 09:41
0

without using iterators also solves the issue.. All i wanted to do is get the index which are to be deleted and sort it in decending order then remove it from the list. check the code below

Arraylist<obj> addlist = getlist();
List<Integer> indices = new ArrayList<Integer>();
    for(int i=0; i<addlist.size() ;i++){
        if(addlist.get(i).getDelete()){
            indices.add(i);

        }
    }
    Collections.sort(indices, Collections.reverseOrder());
    for (int i : indices)
        addlist.remove(i);
Rakshi
  • 6,796
  • 3
  • 25
  • 46