Should I Implement the Arcane Iterator.remove() Method? Yes You (Probably) Should

An interesting question was asked on reddit’s /r/java recently:
Should Iterators be used to modify a custom Collection?
Paraphrasing the question: The author wondered whether a custom java.util.Iterator that is returned from a mutable Collection.iterator() method should implement the weird Iterator.remove() method. A totally understandable question.

What does Iterator.remove() do?

Few people ever use this method at all. For instance, if you want to implement a generic way to remove null values from an arbitrary Collection, this would be the most generic approach:

Collection<Integer> collection =
Stream.of(1, 2, null, 3, 4, null, 5, 6)
      .collect(Collectors.toCollection(ArrayList::new));

System.out.println(collection);

Iterator<Integer> it = collection.iterator();
while (it.hasNext())
    if (it.next() == null)
        it.remove();

System.out.println(collection);

The above program will print:
[1, 2, null, 3, 4, null, 5, 6]
[1, 2, 3, 4, 5, 6]
Somehow, this API usage does feel dirty. An Iterator seems to be useful to … well … iterate its backing collection. It’s really weird that it also allows for modifying it. It’s even weirder that it only offers removal. E.g. we cannot add a new element before or after the current element of iteration, or replace it. Luckily, Java 8 provides us with a much better method on the Collection API directly, namely Collection.removeIf(Predicate). The above iteration code can be re-written as such:

collection.removeIf(Objects::isNull);

OK, now should I implement remove() on my own iterators?

Yes, you should – if your custom collection is mutable. For a very simple reason. Check out the default implementation of Collection.removeIf():

default boolean removeIf(Predicate<? super E> filter) {
    Objects.requireNonNull(filter);
    boolean removed = false;
    final Iterator<E> each = iterator();
    while (each.hasNext()) {
        if (filter.test(each.next())) {
            each.remove();
            removed = true;
        }
    }
    return removed;
}

As I said. The most generic way to remove specific elements from a Collection is precisely to go by its Iterator.remove() method and that’s precisely what the JDK does. Subtypes like ArrayList may of course override this implementation because there’s a more performant alternative, but in general, if you write your own custom, modifiable collection, you should implement this method. And enjoy the ride into Java’s peculiar, historic caveats for which we all love the language.

4 thoughts on “Should I Implement the Arcane Iterator.remove() Method? Yes You (Probably) Should

  1. Thanks, good to know that Collection.removeIf() relies on Iterator.remove().

    For adding elements during iteration there’s ListIterator. It’s only available for Lists as adding elements during iteration only makes sense for ordered Collections, eg for Lists but not for Sets.

  2. The much more general principle here is don’t EVER implement an interface without implementing all of the methods unless you have a good reason to prevent that operation from ever occurring. The fact that here you know of something that will try to use this method is a good example of why, but one should not need to know of a specific case to decide to implement such a method…the larger point should be you don’t know what may try to use a given method, so unless you really don’t need your code to inter-operate with code not under your direct control or have a positive need to prevent the operation in question from happening, not implementing such a method should not be considered an option.

Leave a Reply