Java – Iterable collections that can be changed during iteration

Iterable collections that can be changed during iteration… here is a solution to the problem.

Iterable collections that can be changed during iteration

Is there an iterative collection data structure in Java (and C#, if you know) with the following properties:

  • You can delete the current element without affecting the current iterator (the rest of the iterator iteration that has been started).
  • New elements can be added, but they do not affect the current iterator — they are not included as iteration values while the iteration of the current iterator is still in progress. In my case, only one new element will be added per iteration, but no element will be seen until a new iterator is fetched from the iterable.
  • The order of the elements does not matter.

In fact, there is an incoming list and an outgoing list of items. Incoming lists are iterated over and some are copied to a new list. During the iteration process, some new elements can be added to the new list. At the end of the iteration, the old incoming list is replaced by the new outgoing list. The whole process is a cycle in itself.

Therefore, it seems inefficient to copy elements to a newly constructed collection object each time compared to a collection object with these add/remove properties.

I’m thinking about some kind of queue that would let me preview the current item, then dequeue it or not, and then move to the next item. I can add more items to the head of the queue, but I can’t see them because I’m moving towards the tail. A doubly linked list can have these properties, right?

If you really want to know what it’s for, add a second big block of code in an answer of mine

Solution

In C#, it’s easy to do this using List<T> and for(...). instead of foreach (...) :

using System;
using System.Collections.Generic;
using System.Linq;

namespace Demo
{
    static class Program
    {
        static void Main()
        {
            List<int> list = Enumerable.Range(1, 10). ToList();

for (int i = 0; i < list. Count; ++i)
            {
                if ((list[i] % 3) == 0) // Remove multiples of 3.
                    list. RemoveAt(i--);  NOTE: Post-decrement i
                else if ((list[i] % 4) == 0) // At each multiple of 4, add (2*value+1)
                    list. Add(list[i] * 2 + 1);
                else
                    ;  Do nothing.
            }

Console.WriteLine(string. Join(", ", list));  Outputs 1, 2, 4, 5, 7, 8, 10, 17
        }
    }
}

The key here is to use an index instead of foreach, and not to change anything until the current index (not required according to your requirements).

However, if you really need to add or remove elements before the current index, then this approach doesn’t work (or at least, it gets more complicated).

Related Problems and Solutions