ArrayList Behavior on remove(index)
When you do:
list.remove(i);
- It removes the element at index
i
. - All subsequent elements are shifted left (i.e., index
i+1
becomesi
, and so on). - So, if you increment the index normally after a removal, you skip the next element!
✅ When to Decrement or Avoid Incrementing
You should not increment the index after removing an element if you’re doing a forward iteration. Either:
- Manually decrement the index:
for (int i = 0; i < list.size(); i++)
{
if (shouldRemove(list.get(i)))
{
list.remove(i);
i--; // adjust for shift
}
}
- Or iterate backward to avoid this problem:
for (int i = list.size() - 1; i >= 0; i--)
{
if (shouldRemove(list.get(i)))
{
list.remove(i); // no need to adjust index
}
}
When you iterate backward through an ArrayList, you avoid index adjustment after removal because removing an element does not affect the earlier elements — the ones you haven’t visited yet.
Forward Iteration (why it’s risky):
for (int i = 0; i < list.size(); i++) {
if (list.get(i).equals(“removeMe”)) {
list.remove(i);
i–; // you need this
}
}
When you remove an element at index i
, everything shifts left.
If you then increment i
, you skip the next item.
Backward Iteration (why it’s safe):
for (int i = list.size() – 1; i >= 0; i–) {
if (list.get(i).equals(“removeMe”)) {
list.remove(i);
}
}
You start from the end of the list.
If you remove an element at index i
, nothing after it shifts, because you’re moving toward the beginning.
So each item still appears at the same index it was originally at, and you’re not skipping anything.
Let’s break this down with a real example:
List list = new ArrayList<>(List.of(“A”, “B”, “C”, “D”, “E”));
for (int i = list.size() – 1; i >= 0; i–) {
if (list.get(i).equals(“C”)) {
list.remove(i);
}
}
Step-by-step:
- Initial list:
["A", "B", "C", "D", "E"]
i = 4
→ “E” → skipi = 3
→ “D” → skipi = 2
→ “C” → ✅ remove it- Now list becomes:
["A", "B", "D", "E"]
- Now list becomes:
- Next
i = 1
→ “B” → no problem — we’re not touching any index that was shifted
So yes:
- The list shrinks,
- The shift happens (elements after index
2
move one step left), - But because you’re already done with those higher indexes (
i = 3, 4
), the shift does not break the loop logic or cause skips.
Ahh I got it now, so it is as simple as always decrementing the index whenever an element is removed? Sorry, there is more to the story 🙂
for (int i = 0; i < list.size(); i++) {
if (condition) {
list.remove(i);
i–; // ← seems like this should work, right?
}
}
Why this can fail:
Because the for
loop automatically increments i
after every iteration. If you manually do i--
inside the loop, the next loop iteration still does i++
right after — and the net effect may still skip elements if the logic isn’t carefully controlled.
So i--
only works if you do not let the loop increment i
again.
for (int i = 0; i < list.size(); ) {
if (condition) {
list.remove(i);
// i is NOT incremented — you re-check this index
} else {
i++;
}
}
This avoids the automatic i++
of a standard for
loop. It gives you complete control.
Real Example: Why i--
Alone Fails
Let’s say the list is:
[ “A”, “B”, “C”, “D”, “E” ]
for (int i = 0; i < list.size(); i++) {
if (list.get(i).equals(“B”) || list.get(i).equals(“D”)) {
list.remove(i);
i–;
}
}
Steps:
i = 0
, value"A"
→ skipi = 1
, value"B"
→ remove,i-- → i = 0
- Next iteration:
i++ → i = 1
(value now"C"
) → skipped i = 2
, value"D"
→ remove,i-- → i = 1
- Next iteration:
i++ → i = 2
(value now"E"
) → skipped
⛔ "C"
and "E"
were never checked for removal, because of alternating skips due to the i--
/i++
combination.
Bottom Line
“Always use
i--
when removing” is a dangerous oversimplification.
“Manually control the index when removing during forward iteration” is safer and predictable.
Approach | Safe? | Notes |
---|---|---|
i-- after remove(i) inside normal for (i++) loop | Risk of skipping elements | |
Use for (; i < list.size(); ) and only increment i when not removing | Most reliable | |
Iterate backward (i-- ) | Easiest and safest | |
Use Iterator with remove() | Best for readability and safety |