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();
}
}