Well, I just went with multiple Lists.
For this purpose I wrote this class, maybe somebody else can find use for it:
import java.util.ArrayList; import java.util.ConcurrentModificationException; import java.util.Iterator; import java.util.List; public class BufferedCollection<E> implements Iterable<E> { /** * Holds data to be iterated over */ private final List<E> buffer; /** * Holds data to be inserted into the main buffer before the next iteration */ private final List<E> insertBuffer; /** * Holds data to be removed from the main buffer or the insertion buffer before the next iteration */ private final List<E> deleteBuffer; public BufferedCollection() { buffer = new ArrayList<>(); insertBuffer = new ArrayList<>(3); deleteBuffer = new ArrayList<>(3); } /** * Returns the number of elements that will be iterated over the next time an Iterator is created. * * @return Number of elements in this collection ignoring buffers */ public int getCurrentSize() { return buffer.size(); } /** * Makes a best effort to predict the size of this collection after the next {@link #mergeBuffers()} has been called. * The returned value might not be accurate all the time. * * @return Predicted number of elements in this collection and buffers * @see #bufferedInsert(Object) * @see #bufferedDelete(Object) * @see #mergeBuffers() */ public int getExpectedSize() { return (buffer.size() + insertBuffer.size()) - deleteBuffer.size(); } /** * The given object will be inserted into this collection after the next call to {@link #mergeBuffers()}. * * @param obs */ public void bufferedInsert(E obs) { insertBuffer.add(obs); } /** * The given object will be removed from this collection after the next call to {@link #mergeBuffers()}. * <br> * The object will also be removed if it was supposed to be inserted at the same time. * * @param obs */ public void bufferedDelete(E obs) { deleteBuffer.add(obs); } /** * This method will carry out all pending insertion and deletion events on this collection. * This should not happen while an iteration over this collection is taking place. * Ideally you would want to call this method before an iteration starts. * <br> * If this method is called during an iteration over the elements within this collection a {@link ConcurrentModificationException} will be thrown. * * @see #bufferedInsert(Object) * @see #bufferedDelete(Object) */ public void mergeBuffers() { buffer.addAll(insertBuffer); insertBuffer.clear(); buffer.removeAll(deleteBuffer); deleteBuffer.clear(); } public Iterator<E> iterator() { return buffer.iterator(); } public String toString() { return buffer.toString(); } }