Altinet
  • Home
  • Blog
  • Contact





QueueSet, Hashed Queue, HashQueue, Weighted List, Hashed History or some other name, couldn’t find it online:)

On 03 Jan, 2011
.NET
By : Bruno Samardzic
No Comments
Views : 3739

Ok so i had trouble even expressing what I needed so i had to build it myself. So what is it?
Well, it’s basically a hashed queue where when you enqueue again an already queued item, you basically put it in the first spot. It’s made as a collection but it still acts as a queue. I needed it for my taskbar which automatically closes the least active item, or the one least used. so here you go:

public class BindableQueueSet<T> : ICollection<T>, INotifyCollectionChanged,INotifyPropertyChanged
    {
        private readonly ObservableCollection<Pair> que;

        private int maxNumber;
        private readonly int capacity;

        #region Private and protected

        private bool AddItemCore(T item)
        {
            bool result;
            var found = que.FirstOrDefault(x => x.Value.Equals(item));
            if (found == null)
            {
                que.Add(new Pair(item, maxNumber++));
                result = true;
            }
            else
            {
                found.Weight = maxNumber++;
                result = false;
            }
            result = CleanUp() || result;
            return result;
        }


        private Pair Find(T item)
        {
            return que.FirstOrDefault(x => x.Value.Equals(item));
        }

        private bool CleanUp()
        {
            if (capacity >= que.Count) return false;
            Pair lightestPair = que[0];
            foreach (var pair in que)
            {
                if (pair.Weight < lightestPair.Weight)
                    lightestPair = pair;
            }
            que.Remove(lightestPair);
            return true;
        }

        #endregion

        public BindableQueueSet(int capacity)
        {
            if (capacity < 1) throw new ArgumentException();
            this.capacity = capacity;
            que = new ObservableCollection<Pair>();
            que.CollectionChanged += (s, e) => OnCollectionChanged(e);
            ((INotifyPropertyChanged) que).PropertyChanged += (s, e) => OnPropertyChanged(e);
        }

        private void OnPropertyChanged(PropertyChangedEventArgs e)
        {
            if (PropertyChanged != null)
                PropertyChanged(this, e);
        }

        void OnCollectionChanged(NotifyCollectionChangedEventArgs e)
        {

            NotifyCollectionChangedEventArgs enew;
            switch (e.Action)
            {
                case NotifyCollectionChangedAction.Replace:
                    enew = new NotifyCollectionChangedEventArgs(e.Action,
                                                                e.NewItems != null && e.NewItems.Count > 0
                                                                    ? ((Pair) e.NewItems[0]).Value:default(T),
                                                                e.OldItems != null && e.OldItems.Count > 0
                                                                    ? ((Pair) e.OldItems[0]).Value:default(T),
                                                                e.NewStartingIndex);
                    break;
                case NotifyCollectionChangedAction.Add:
                    enew = new NotifyCollectionChangedEventArgs(e.Action,
                                                                e.NewItems != null && e.NewItems.Count > 0
                                                                    ? ((Pair)e.NewItems[0]).Value : default(T),
                                                                e.NewStartingIndex);
                    break;
                case NotifyCollectionChangedAction.Remove:
                    enew = new NotifyCollectionChangedEventArgs(e.Action,
                                                                e.OldItems != null && e.OldItems.Count > 0
                                                                    ? ((Pair)e.OldItems[0]).Value : default(T),
                                                                e.OldStartingIndex);
                    break;
                default:
                    enew = new NotifyCollectionChangedEventArgs(e.Action);
                    break;
            }
            if (CollectionChanged != null)
                CollectionChanged(this, enew);
        }



        public IEnumerator<T> GetEnumerator()
        {
            return new QueueEnum(que.GetEnumerator());
        }

        IEnumerator IEnumerable.GetEnumerator()
        {
            return GetEnumerator();
        }

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

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

        public bool Contains(T item)
        {
            return Find(item) != null;
        }

        public void CopyTo(T[] array, int arrayIndex)
        {
            while (arrayIndex < array.Length)
            {
                AddItemCore(array[arrayIndex]);
                arrayIndex++;
            }
        }

        public bool Remove(T item)
        {
            var found = Find(item);
            return que.Remove(found);
        }

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

        public bool IsReadOnly
        {
            get { return false; }
        }

        public event NotifyCollectionChangedEventHandler CollectionChanged;

        private class Pair
        {
            public int Weight { get; set; }
            public T Value { get; private set; }
            public Pair(T value, int weight)
            {
                Value = value;
                Weight = weight;
            }
        }

        private class QueueEnum : IEnumerator<T>
        {
            private readonly IEnumerator<Pair> queEnum;

            public QueueEnum(IEnumerator<Pair> queEnum)
            {
                this.queEnum = queEnum;
            }

            public void Dispose()
            {
                queEnum.Dispose();
            }

            public bool MoveNext()
            {
                return queEnum.MoveNext();
            }

            public void Reset()
            {
                queEnum.Reset();
            }

            public T Current
            {
                get { return queEnum.Current.Value; }
            }

            object IEnumerator.Current
            {
                get { return Current; }
            }
        }

        public event PropertyChangedEventHandler PropertyChanged;
    }


Previous Post Next Post 

About The Author

Bruno Samardzic


Number of Posts : 45
All Posts by : Bruno Samardzic

Leave a Comment

Click here to cancel reply

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>





Recent Posts

  • Angular vs React: round 2
  • Why programming is hard
  • Orchard Workflows, undocumented gem
  • The React Redux
  • React.js invoicing CRUD application, part 2: Description

Recent Comments

  • Angshuman on Animation for starred grid rows and columns using xaml
  • Advanced Excel Training in Lucknow on Angular vs React: round 2
  • Reginald Sophomore on My example of Angularjs directive
  • Slobodan on Angular and Breeze – story so far.
  • Bruno Samardzic on Reaction to Ember-forged Durandal Angularly Knocking out my Backbone, or my JS MVC framework research conclusion.

Contact

Altinet d.o.o.

OIB: 97429091194

Čulinečka cesta 146, Zagreb

Tel: +385 (1) 2946 819

Mob: +385 (98) 210 756

IBAN: HR4323400091110406470

Latest tweets