Search code examples
javacollectionsframeworksconcurrent-collections

Java collection to allow adding and removing while iterating


I am interested if there is any framework that implements a collection that would have the following behavior.


Suppose it initially contains: [1, 2, 3]

  • I iterate it (using an iterator) and reach element 2, now I add 4 to the end (the collection will now be [1, 2, 3, 4]).
  • now I create a new iterator and iterate the collection, resulting in [1, 2, 3, 4]
  • I continue iterating with the first iterator and it will give me just 3 and return
  • now resetting the first iterator will give me [1, 2, 3, 4] (similar to creating a new one).

Same should apply for removal of elements. If I remove 3 instead of adding, the second iterator should give me [1, 2] while the first one will still give me 3 and the end.


So when I get and iterator I want it to give me the collection I had when I created the iterator (even if I iterate it later, on I iterate a bit and continue later), when I reset the iterator, it gets garbage collected it will update to the latest versions and I should be able to have multiple iterator instances created at different times that will give different versions depending on the contents of the array when the iterator was created.

I would need it to work well with multiple threads and preferable have an efficient implementation.

Does anyone know of any implementation of such a collection, or do I have to implement it myself?


Solution

  • What you describe looks very similar to how CopyOnWriteArrayList works:

    • once you start iterating, you can change the collection (including from another thread) without affecting the iteration
    • if you create a new iterator it will be based on the collection at the creation time
    • it is thread safe

    Simple example below with the following output:

    Iterator 1 - 1
    4 has been added
    Iterator 2 - 1
    Iterator 2 - 2
    Iterator 2 - 3
    Iterator 2 - 4
    Iterator 1 - 2
    Iterator 1 - 3

    public static void main(String[] args) throws InterruptedException {
        final List<Integer> list = new CopyOnWriteArrayList<Integer>();
        list.addAll(Arrays.asList(1, 2, 3));
        new Thread(new Runnable() {
    
            @Override
            public void run() {
                for (Integer i : list) {
                    System.out.println("Iterator 1 - " + i);
                    try {
                        Thread.sleep(10);
                    } catch (InterruptedException e) {}
                }
            }
        }).start();
        Thread.sleep(10);
        list.add(4);
        System.out.println("4 has been added");
        for (Integer i : list) {
            System.out.println("Iterator 2 - " + i);
        }
    
    }