Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

First-in-first-out collection with maximum size and no duplication?

.NET seems to have a lot of data structure and collection types. Does it have a first-in-first-out collection with a maximum size and no duplication, or something similar to that?

An example usage would be like for storing 5 most recently opened files. If a 6th object is added, dequeue the least recent object to keep the size to 5

like image 550
Louis Rhys Avatar asked Oct 10 '22 23:10

Louis Rhys


2 Answers

You'll have to create a QueueSet that implements ICollection<T>. It can be a wrapper class that contains a collection as a backing store. It can be implemented as follows:

class QueueSet<T> : ICollection<T> 
{
    List<T> queue=new List<T>();
    int maximumSize;

    public QueueSet(int maximumSize){
        if(maximumSize<0)
            throw new ArgumentOutOfRangeException("maximumSize");
        this.maximumSize=maximumSize;
    }

    public T Dequeue(){
        if(queue.Count>0){
            T value=queue[0];
            queue.RemoveAt(0);
            return value;
        }
        return default(T);
    }

    public T Peek(){
        if(queue.Count>0){
            return queue[0];
        }
        return default(T);
    }

    public void Enqueue(T item){
        if(queue.Contains(item)){
            queue.Remove(item);
        }
        queue.Add(item);
        while(queue.Count>maximumSize){
            Dequeue();
        }
    }

    public int Count {
        get {
            return queue.Count;
        }
    }

    public bool IsReadOnly {
        get {
            return false;
        }
    }

    public void Add(T item)
    {
        Enqueue(item);
    }

    public void Clear()
    {
        queue.Clear();
    }

    public bool Contains(T item)
    {
        return queue.Contains(item);
    }

    public void CopyTo(T[] array, int arrayIndex)
    {
        foreach(T value in queue){
            if(arrayIndex>=array.Length)break;
            if(arrayIndex>=0){
                array[arrayIndex]=value;
            }
            arrayIndex++;
        }
    }

    public bool Remove(T item)
    {
        if(Object.Equals(item,Peek())){
           Dequeue();
           return true;
        } else {
            return false;
        }
    }

    public IEnumerator<T> GetEnumerator()
    {
        return queue.GetEnumerator();
    }

    System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
    {
        return queue.GetEnumerator();
    }
}

I release this code into the public domain.

like image 147
Peter O. Avatar answered Oct 18 '22 06:10

Peter O.


You want a queue, no?

It doesn't really support maximum size and no duplication but you could inherit from Queue and add those features.

You could do so by overriding the Enqueue method. Something like this might work (but throw more appropriate exception types!):

    public class LimitedQueue : Queue
    {
        public override void Enqueue(object obj)
        {
            if (this.Count > 5)
                throw new Exception();

            if(this.Contains(obj))
                throw new Exception();
            base.Enqueue(obj);
        }
    }

A containing or wrapper or HAS-A class might look like this:

public class QueueWrapper<T>
{
     private Queue<T> _queue;
     public void Enqueue(T item)
     {
         if (_queue.Count > 5)
             throw new Exception();

         if(this.Contains(item))
             throw new Exception();

         _queue.Enqueue(item);
     }

     //Any other methods you might want to use would also need to be exposed similarly
}
like image 34
rtalbot Avatar answered Oct 18 '22 06:10

rtalbot