codelessgenie blog

How to Delete a Range of Values from a List Using Iterator

When working with lists in Java, modifying elements (especially deleting a range) during iteration can be error-prone. The enhanced for loop (for-each) throws a ConcurrentModificationException if the list is modified mid-iteration. Using a Iterator (or ListIterator) provides a safe and efficient way to delete a range of values while iterating, avoiding such exceptions. This blog explains the process, best practices, and real-world use cases.

2026-06

Table of Contents#

  1. Understanding the Need for Iterator in Range Deletion
  2. Basics of Java Iterator
  3. Deleting a Range of Values: Step-by-Step
  4. Example Implementations
  5. Common Pitfalls and Best Practices
  6. Alternative Approaches
  7. Real-World Use Cases
  8. Conclusion
  9. References

1. Understanding the Need for Iterator in Range Deletion#

Problem with Enhanced for Loop#

The enhanced for loop (e.g., for (T element : list)) uses an implicit iterator. If you modify the list (e.g., list.remove(element)) during iteration, the iterator’s internal state (tracking modifications) gets out of sync, triggering a ConcurrentModificationException.

Problem with Index-Based for Loop#

An index-based for loop (e.g., for (int i=0; i<list.size(); i++)) works but is error-prone:

  • Deleting an element shifts subsequent indices, leading to skipped elements or IndexOutOfBoundsException.
  • Complex logic for range-based deletion (e.g., deleting elements between indices x and y) becomes hard to manage.

2. Basics of Java Iterator#

The java.util.Iterator interface provides methods to traverse and modify a collection safely during iteration:

MethodDescription
hasNext()Checks if there is a next element (returns true/false).
next()Returns the next element (throws NoSuchElementException if none exists).
remove()Deletes the last element returned by next() (throws IllegalStateException if misused).

Simple Example: Removing a Single Element#

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
 
public class IteratorBasics {
    public static void main(String[] args) {
        List<String> fruits = new ArrayList<>(Arrays.asList("Apple", "Banana", "Cherry"));
        Iterator<String> it = fruits.iterator();
        
        while (it.hasNext()) {
            String fruit = it.next();
            if (fruit.equals("Banana")) {
                it.remove(); // Safely remove "Banana"
            }
        }
        
        System.out.println(fruits); // Output: [Apple, Cherry]
    }
}

3. Deleting a Range of Values: Step-by-Step#

To delete a range of values (e.g., elements between two values, indices, or a condition):

Step 1: Define the Range#

  • Value-based range: Delete elements between min and max (e.g., all integers from 5 to 10).
  • Index-based range: Delete elements at indices start to end (e.g., indices 1 to 3).
  • Condition-based range: Delete elements matching a predicate (e.g., all strings longer than 5 characters).

Step 2: Iterate with Iterator#

  • Use hasNext() to check for remaining elements.
  • Use next() to fetch the current element.
  • Check if the element falls within the range.
  • If yes, call remove() to delete it.

4. Example Implementations#

Example 1: Value-Based Range Deletion (Integers 5–10)#

Delete all integers between 5 and 10 (inclusive) from a list:

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
 
public class RangeDeletionValue {
    public static void main(String[] args) {
        List<Integer> numbers = new ArrayList<>(Arrays.asList(1, 6, 3, 8, 10, 4, 9));
        System.out.println("Before: " + numbers);
 
        Iterator<Integer> it = numbers.iterator();
        while (it.hasNext()) {
            Integer num = it.next();
            // Check if num is in [5, 10]
            if (num >= 5 && num <= 10) {
                it.remove(); // Delete the element
            }
        }
 
        System.out.println("After: " + numbers); // Output: [1, 3, 4]
    }
}

Example 2: Index-Based Range Deletion (Indices 1–3)#

Delete elements at indices 1, 2, and 3 (0-based) from a list:

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
 
public class RangeDeletionIndex {
    public static void main(String[] args) {
        List<String> items = new ArrayList<>(Arrays.asList("A", "B", "C", "D", "E"));
        System.out.println("Before: " + items);
 
        Iterator<String> it = items.iterator();
        int currentIndex = 0; // Track the index manually
 
        while (it.hasNext()) {
            String item = it.next();
            // Delete elements at indices 1, 2, 3
            if (currentIndex >= 1 && currentIndex <= 3) {
                it.remove();
            }
            currentIndex++; // Increment after processing the element
        }
 
        System.out.println("After: " + items); // Output: [A, E]
    }
}

Example 3: Condition-Based Range Deletion (Strings with Length > 5)#

Delete all strings longer than 5 characters:

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
 
public class RangeDeletionCondition {
    public static void main(String[] args) {
        List<String> words = new ArrayList<>(Arrays.asList("Hello", "Programming", "World", "Java"));
        System.out.println("Before: " + words);
 
        Iterator<String> it = words.iterator();
        while (it.hasNext()) {
            String word = it.next();
            // Delete words with length > 5
            if (word.length() > 5) {
                it.remove();
            }
        }
 
        System.out.println("After: " + words); // Output: [Hello, World, Java]
    }
}

5. Common Pitfalls and Best Practices#

Common Pitfalls#

  1. Calling remove() without next():
    Throws IllegalStateException (e.g., it.remove() before it.next()).

    // WRONG: remove() called without next()
    it.remove(); // Throws IllegalStateException
  2. Calling remove() multiple times after next():
    Also throws IllegalStateException (e.g., it.remove(); it.remove(); after one next()).

  3. Modifying the list outside the iterator:
    Causes ConcurrentModificationException (e.g., list.add("New") while iterating with Iterator).

  4. Forgetting hasNext() before next():
    Throws NoSuchElementException (e.g., it.next() when no elements remain).

Best Practices#

  1. Always use Iterator’s remove():
    Never modify the list directly (e.g., list.remove() ) during iteration.

  2. Use a temporary variable for next():
    Store the element from next() in a variable to avoid re-fetching (e.g., String elem = it.next();).

  3. Track indices (for index-based ranges):
    Use a separate variable (e.g., int index = 0;) to track the current index, as Iterator does not expose indices.

  4. Use ListIterator for bidirectional control:
    For more control (e.g., reverse iteration, index access), use ListIterator (supports previous(), nextIndex(), etc.).

  5. Synchronize for concurrent access:
    If the list is shared across threads, synchronize access or use a concurrent collection (e.g., CopyOnWriteArrayList).

6. Alternative Approaches#

Using ListIterator (Bidirectional Iteration)#

ListIterator extends Iterator and supports:

  • Bidirectional movement (previous(), next()).
  • Index tracking (nextIndex(), previousIndex()).
  • In-place modifications (add(), set(), remove()).

Example: Delete elements at indices 1–3 with ListIterator#

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.ListIterator;
 
public class ListIteratorExample {
    public static void main(String[] args) {
        List<String> items = new ArrayList<>(Arrays.asList("A", "B", "C", "D", "E"));
        System.out.println("Before: " + items);
 
        ListIterator<String> lit = items.listIterator();
        int startIndex = 1;
        int endIndex = 3;
 
        while (lit.hasNext()) {
            int currentIndex = lit.nextIndex();
            String item = lit.next();
            if (currentIndex >= startIndex && currentIndex <= endIndex) {
                lit.remove(); // Delete the element
            }
        }
 
        System.out.println("After: " + items); // Output: [A, E]
    }
}

Using Java 8+ Streams (New List, Not In-Place)#

For creating a new list (not modifying the original), use streams with filter():

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
 
public class StreamExample {
    public static void main(String[] args) {
        List<Integer> numbers = new ArrayList<>(Arrays.asList(1, 6, 3, 8, 10, 4, 9));
        // Create a new list with elements NOT in [5, 10]
        List<Integer> filtered = numbers.stream()
                .filter(num -> num < 5 || num > 10)
                .collect(Collectors.toList());
 
        System.out.println("Filtered: " + filtered); // Output: [1, 3, 4]
    }
}

Pros: Concise, functional style.
Cons: Creates a new list (original remains unchanged).

7. Real-World Use Cases#

  • Log File Processing: Remove log entries between two timestamps (value-based range).
  • Batch Data Deletion: Delete old records (e.g., from a list of database entries) based on a date range.
  • Game Development: Remove expired game objects (e.g., power-ups) from a list of active entities.
  • Text Processing: Delete lines between two markers (e.g., <!-- START --> and <!-- END -->) from a list of strings.

8. Conclusion#

Using Iterator (or ListIterator) is the safest way to delete a range of values from a List in Java. It avoids ConcurrentModificationException and simplifies range-based deletion. Remember to:

  • Use hasNext() and next() correctly.
  • Only call remove() once per next().
  • Track indices (or use ListIterator) for complex range logic.

For read-only filtering (creating a new list), Java 8+ streams offer a concise alternative.

9. References#


This blog provides a comprehensive guide to safely deleting a range of values from a List using Iterator, with examples, best practices, and real-world applications.