From 9273abd4c2df584b26841ac9cde958bda0c07769 Mon Sep 17 00:00:00 2001 From: Ben Culkin Date: Sat, 21 Nov 2020 11:02:48 -0500 Subject: Add iterators which don't throw ConcurrentModificationException This adds two iterators (one iterator, one ListIterator) which are guaranteed not to throw a ConcurrentModificationException. The intended use case is allowing you to iterate over a list and modify it at the same time. Note that this will still give odd behavior in the presence of actual concurrency, but that is a deliberate tradeoff. --- src/main/java/bjc/data/NonCMEListIterator.java | 68 ++++++++++++++++++++++++++ 1 file changed, 68 insertions(+) create mode 100644 src/main/java/bjc/data/NonCMEListIterator.java (limited to 'src/main/java/bjc/data/NonCMEListIterator.java') diff --git a/src/main/java/bjc/data/NonCMEListIterator.java b/src/main/java/bjc/data/NonCMEListIterator.java new file mode 100644 index 0000000..6e74a24 --- /dev/null +++ b/src/main/java/bjc/data/NonCMEListIterator.java @@ -0,0 +1,68 @@ +package bjc.data; + +import java.util.*; + +/** + * A ListIterator which is guaranteed to never throw {@link ConcurrentModificationException}. + * + * The intended use case for this iterator is that you want to be able to modify + * a list you are iterating over, and not get an immediate exception. + * + * Note that using this is an agreement that you will not complain if it behaves + * oddly in the face of you concurrently modifying the list, as this class was + * designed with the usecase of modifying the list from the same thread, without + * invalidating the iterators. After all, there is a reason that most iterator + * types throw that exception. + * + * However, sometimes you want to play with fire, even if you might get burnt. + * This allows you to do so. + * + * @author Ben Culkin + * + * @param The type being iterated over. + */ +public class NonCMEListIterator extends NonCMEIterator implements ListIterator { + /** + * Create a new list iterator which won't throw {@link ConcurrentModificationException} + * + * @param source The list to iterate over. + */ + public NonCMEListIterator(List source) { + super(source); + } + + @Override + public boolean hasPrevious() { + return currIndex > 0; + } + + @Override + public ElementType previous() { + return source.get(--currIndex); + } + + @Override + public int nextIndex() { + return currIndex + 1; + } + + @Override + public int previousIndex() { + return currIndex - 1; + } + + @Override + public void remove() { + source.remove(currIndex); + } + + @Override + public void set(ElementType element) { + source.set(currIndex, element); + } + + @Override + public void add(ElementType element) { + source.add(currIndex, element); + } +} -- cgit v1.2.3