Stephopolis
Stephopolis

Reputation: 1795

Removing items from arraylist in an iterative manner

I am removing things from an arraylist while inside a loop. I noticed that when I have two things in a row that need to be removed, it misses the second one. For example, my code checks whether a number in the arraylist is smaller than a static number. I have:

arraylist[2,5,15,30]

and I am checking it against

check = 10

so I have a loop

for (int i=0;i<arraylist.size();i++){
    if(check > arraylist.get(i){
        arraylist.remove(i);
    }
}

I am pretty sure I am missing the second one because originally my arraylist is numbered this way:

          0,1,2, 3
arraylist[2,5,15,30]

And after it removes the first entry it changes it to:

          0,1, 2
arraylist[5,15,30]

And I already checked 0, so I don't need to check it again. Is there a simple way to go about fixing this? Without changing my data structure? Thanks

Upvotes: 0

Views: 112

Answers (6)

Spindizzy
Spindizzy

Reputation: 8974

You could use Iterator or ListIterator. Those interfaces let's you iterate and remove over the collection in one step almost.

Sample Test:

import java.util.ArrayList;
import java.util.List;
import java.util.ListIterator;
import org.junit.Before;
import org.junit.Test;
import static org.junit.Assert.*;

public class ListIteratorTest {

    List<Integer> list;

    @Before
    public void setUp() {
        list = new ArrayList<>();
        list.add(2);
        list.add(5);
        list.add(15);
        list.add(30);
    }


    @Test
    public void testListIterator() {
        ListIterator<Integer> lit = list.listIterator();
        while(lit.hasNext()){
            int val = lit.next();
            if(val > 10){
               lit.remove();
            }
        }

        assertFalse(list.contains(15));
    }
}

Upvotes: 1

Tim B
Tim B

Reputation: 41210

There are three ways to do this.

  1. Use an Iterator<> - there is a remove() function on it which will allow you to remove the current item and the iterator will keep track of tihngs.

  2. Start at the end of the list and iterate backwards.

  3. When you remove the item move your current index left 1.

All of these cases will be quite inefficient if you are removing a lot of items though as you are shuffling the whole list along each time you remove one item. Better would be to do:

// Scan through the array keeping a "read" pointer and a "write" pointer.
int write = 0;
for (int scan=0;scan<arrayList.size();scan++) {
    Integer i arrayList.get(scan);
    // Only copy items that match the check
    if (check <= i) {
      if (scan != write) {
          arrayList.set(write, i);
      }
      write++;
    }
}

// Remove any "dead" entries from the end of the list
while (arrayList.size() > write) {
   arrayList.remove(arrayList.size()-1);
}

Otherwise for every element you remove every other element after that one gets shuffled along. With this code each element only gets shuffled along once no matter how many spots it needs to move by.

Upvotes: 0

Kevin Workman
Kevin Workman

Reputation: 42174

Either use an iterator or loop through the ArrayList backwards.

Upvotes: 4

hichris123
hichris123

Reputation: 10233

You can subtract i by one each time you remove an item from the ArrayList, like this:

for (int i=0;i<arraylist.size();i++){
    if(check > arraylist.get(i){
        arraylist.remove(i);
        i = i--;
    }
}

Upvotes: 1

Evgeniy Dorofeev
Evgeniy Dorofeev

Reputation: 136132

Use Iterator

for (Iterator<Integer> it = list.iterator(); it.hasNext();) {
   if (check > it.next()) {
        it.remove();
   }
}

Upvotes: 1

Алексей
Алексей

Reputation: 1847

Take a look at ArrayList#remove it says:

Removes the element at the specified position in this list. Shifts any subsequent elements to the left (subtracts one from their indices).

So you can either do it backward or whenever you delete an element decrement your loop counter

Upvotes: 1

Related Questions