具有最大大小且无重复的先进先出集合?

发布于 2024-12-04 17:57:49 字数 121 浏览 0 评论 0原文

.NET 似乎有很多数据结构和集合类型。它是否有一个具有最大大小且没有重复的先进先出集合,或者类似的东西?

一个示例用法是存储 5 个最近打开的文件。如果添加了第 6 个对象,则将最近的对象出列以将大小保持为 5

.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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

ら栖息 2024-12-11 17:57:49

您必须创建一个实现 ICollectionQueueSet。它可以是包含集合作为后备存储的包装类。它可以按如下方式实现:

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

我将此代码发布到公共领域。

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.

浅笑轻吟梦一曲 2024-12-11 17:57:49

您想要一个队列,不是吗?

它并不真正支持最大大小和无重复,但您可以从 Queue 继承并添加这些功能。

您可以通过重写 Enqueue 方法来做到这一点。像这样的东西可能会起作用(但抛出更合适的异常类型!):

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

包含类或包装类或 HAS-A 类可能如下所示:

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
}

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
}
从来不烧饼 2024-12-11 17:57:49

看看这个: 限制队列大小在.NET中?

你基本上需要一个Queue,如果你设法限制它的大小并让它“索引”或“唯一”,那么你就可以了:)

我相信一点逻辑围绕 Dictionary 也可以,您将存储的数据类型是什么?字符串?

have a look at this: Limit size of Queue<T> in .NET?

you basically need a Queue, if you manage to limit its size and get it "indexed" or "unique" then you are ok :)

I believe a bit of logic around a Dictionary would also work, what is the data type you will store? Strings?

﹏半生如梦愿梦如真 2024-12-11 17:57:49

这就是您想要的,HashQueue,哈希队列集。

添加了一些线程锁,防止意外锁定。请记住,所有 HashSet 操作都会破坏现有队列的顺序。

using System;
using System.Collections;
using System.Collections.Generic;
using System.Runtime.Serialization;
using System.Security.Permissions;

namespace ConsoleApplication
{
    internal class Program
    {
        [Serializable]
        private class HashQueue<T> : ISerializable, IDeserializationCallback, ISet<T>, ICollection<T>, IEnumerable<T>, IEnumerable
        {
            private int _maxCount;
            private Queue<T> _queue = new Queue<T>();
            private HashSet<T> _set = new HashSet<T>();

            public HashQueue(int maxCount = 0)
            {
                if (maxCount < 0) throw new ArgumentOutOfRangeException("maxCount");
                _maxCount = maxCount;
            }

            public bool Add(T item)
            {
                lock (this)
                {
                    if (_queue.Count == _maxCount)
                    {
                        _set.Remove(_queue.Dequeue());
                    }
                    if (_set.Add(item))
                    {
                        _queue.Enqueue(item);
                        return true;
                    }
                    return false;
                }
            }

            public bool Remove(T item)
            {
                lock (this)
                {
                    if (object.ReferenceEquals(_queue.Peek(), item))
                    {
                        return _set.Remove(_queue.Dequeue());
                    }
                    return false;
                }
            }

            public void Clear()
            {
                lock (this)
                {
                    _set.Clear();
                    _queue.Clear();
                }
            }

            public bool Contains(T item)
            {
                lock (this)
                {
                    return _set.Contains(item);
                }
            }

            public void CopyTo(T[] array, int arrayIndex)
            {
                lock (this)
                {
                    _queue.CopyTo(array, arrayIndex);
                }
            }

            public int Count
            {
                get
                {
                    lock (this)
                    {
                        return _queue.Count;
                    }
                }
            }

            public bool IsReadOnly
            {
                get
                {
                    return false;
                }
            }

            public void ProcessItems(Action<T> action)
            {
                lock (this)
                {
                    foreach (T item in _queue)
                    {
                        action(item);
                    }
                }
            }

            void ICollection<T>.Add(T item)
            {
                lock (this)
                {
                    if (_queue.Count == _maxCount)
                    {
                        _set.Remove(_queue.Dequeue());
                    }
                    if (!_set.Add(item))
                    {
                        throw new ArgumentOutOfRangeException("item");
                    }
                    _queue.Enqueue(item);
                }
            }

            public IEnumerator<T> GetEnumerator()
            {
                lock (this)
                {
                    return _queue.GetEnumerator();
                }
            }

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

            public void OnDeserialization(object sender)
            {
                lock (this)
                {
                    _set.OnDeserialization(sender);
                }
            }

            private void RebuildQuery()
            {
                _queue.Clear();
                foreach (T item in _set)
                {
                    _queue.Enqueue(item);
                }
            }

            public void ExceptWith(IEnumerable<T> other)
            {
                lock (this)
                {
                    _set.ExceptWith(other);
                    RebuildQuery();
                }
            }

            public void IntersectWith(IEnumerable<T> other)
            {
                lock (this)
                {
                    _set.IntersectWith(other);
                    RebuildQuery();
                }
            }

            public bool IsProperSubsetOf(IEnumerable<T> other)
            {
                lock (this)
                {
                    return _set.IsProperSubsetOf(other);
                }
            }

            public bool IsProperSupersetOf(IEnumerable<T> other)
            {
                lock (this)
                {
                    return _set.IsProperSupersetOf(other);
                }
            }

            public bool IsSubsetOf(IEnumerable<T> other)
            {
                lock (this)
                {
                    return _set.IsSubsetOf(other);
                }
            }

            public bool IsSupersetOf(IEnumerable<T> other)
            {
                lock (this)
                {
                    return _set.IsSupersetOf(other);
                }
            }

            public bool Overlaps(IEnumerable<T> other)
            {
                lock (this)
                {
                    return _set.Overlaps(other);
                }
            }

            public bool SetEquals(IEnumerable<T> other)
            {
                lock (this)
                {
                    return _set.SetEquals(other);
                }
            }

            public void SymmetricExceptWith(IEnumerable<T> other)
            {
                lock (this)
                {
                    _set.SymmetricExceptWith(other);
                    RebuildQuery();
                }
            }

            public void UnionWith(IEnumerable<T> other)
            {
                lock (this)
                {
                    _set.UnionWith(other);
                    RebuildQuery();
                }
            }

            [SecurityPermissionAttribute(SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.SerializationFormatter)]
            void ISerializable.GetObjectData(SerializationInfo info, StreamingContext context)
            {
                _set.GetObjectData(info, context);
            }
        }

        private static void Main(string[] args)
        {
            HashQueue<int> queue = new HashQueue<int>(5);
            queue.Add(1);
            queue.Add(2);
            queue.Add(3);
            queue.Add(4);
            queue.Add(5);
            queue.Add(6);
            queue.ProcessItems((i) => Console.Write(i));
            //foreach (int i in queue)
            //{
            //    Console.Write("{0}", i);
            //}
        }
    }
}

This is what you want, HashQueue<T>, the hashed queued set.

Added some thread locks, protects from accidental locks. Keep in mind, that all HashSet operation breaks the order of existing queue.

using System;
using System.Collections;
using System.Collections.Generic;
using System.Runtime.Serialization;
using System.Security.Permissions;

namespace ConsoleApplication
{
    internal class Program
    {
        [Serializable]
        private class HashQueue<T> : ISerializable, IDeserializationCallback, ISet<T>, ICollection<T>, IEnumerable<T>, IEnumerable
        {
            private int _maxCount;
            private Queue<T> _queue = new Queue<T>();
            private HashSet<T> _set = new HashSet<T>();

            public HashQueue(int maxCount = 0)
            {
                if (maxCount < 0) throw new ArgumentOutOfRangeException("maxCount");
                _maxCount = maxCount;
            }

            public bool Add(T item)
            {
                lock (this)
                {
                    if (_queue.Count == _maxCount)
                    {
                        _set.Remove(_queue.Dequeue());
                    }
                    if (_set.Add(item))
                    {
                        _queue.Enqueue(item);
                        return true;
                    }
                    return false;
                }
            }

            public bool Remove(T item)
            {
                lock (this)
                {
                    if (object.ReferenceEquals(_queue.Peek(), item))
                    {
                        return _set.Remove(_queue.Dequeue());
                    }
                    return false;
                }
            }

            public void Clear()
            {
                lock (this)
                {
                    _set.Clear();
                    _queue.Clear();
                }
            }

            public bool Contains(T item)
            {
                lock (this)
                {
                    return _set.Contains(item);
                }
            }

            public void CopyTo(T[] array, int arrayIndex)
            {
                lock (this)
                {
                    _queue.CopyTo(array, arrayIndex);
                }
            }

            public int Count
            {
                get
                {
                    lock (this)
                    {
                        return _queue.Count;
                    }
                }
            }

            public bool IsReadOnly
            {
                get
                {
                    return false;
                }
            }

            public void ProcessItems(Action<T> action)
            {
                lock (this)
                {
                    foreach (T item in _queue)
                    {
                        action(item);
                    }
                }
            }

            void ICollection<T>.Add(T item)
            {
                lock (this)
                {
                    if (_queue.Count == _maxCount)
                    {
                        _set.Remove(_queue.Dequeue());
                    }
                    if (!_set.Add(item))
                    {
                        throw new ArgumentOutOfRangeException("item");
                    }
                    _queue.Enqueue(item);
                }
            }

            public IEnumerator<T> GetEnumerator()
            {
                lock (this)
                {
                    return _queue.GetEnumerator();
                }
            }

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

            public void OnDeserialization(object sender)
            {
                lock (this)
                {
                    _set.OnDeserialization(sender);
                }
            }

            private void RebuildQuery()
            {
                _queue.Clear();
                foreach (T item in _set)
                {
                    _queue.Enqueue(item);
                }
            }

            public void ExceptWith(IEnumerable<T> other)
            {
                lock (this)
                {
                    _set.ExceptWith(other);
                    RebuildQuery();
                }
            }

            public void IntersectWith(IEnumerable<T> other)
            {
                lock (this)
                {
                    _set.IntersectWith(other);
                    RebuildQuery();
                }
            }

            public bool IsProperSubsetOf(IEnumerable<T> other)
            {
                lock (this)
                {
                    return _set.IsProperSubsetOf(other);
                }
            }

            public bool IsProperSupersetOf(IEnumerable<T> other)
            {
                lock (this)
                {
                    return _set.IsProperSupersetOf(other);
                }
            }

            public bool IsSubsetOf(IEnumerable<T> other)
            {
                lock (this)
                {
                    return _set.IsSubsetOf(other);
                }
            }

            public bool IsSupersetOf(IEnumerable<T> other)
            {
                lock (this)
                {
                    return _set.IsSupersetOf(other);
                }
            }

            public bool Overlaps(IEnumerable<T> other)
            {
                lock (this)
                {
                    return _set.Overlaps(other);
                }
            }

            public bool SetEquals(IEnumerable<T> other)
            {
                lock (this)
                {
                    return _set.SetEquals(other);
                }
            }

            public void SymmetricExceptWith(IEnumerable<T> other)
            {
                lock (this)
                {
                    _set.SymmetricExceptWith(other);
                    RebuildQuery();
                }
            }

            public void UnionWith(IEnumerable<T> other)
            {
                lock (this)
                {
                    _set.UnionWith(other);
                    RebuildQuery();
                }
            }

            [SecurityPermissionAttribute(SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.SerializationFormatter)]
            void ISerializable.GetObjectData(SerializationInfo info, StreamingContext context)
            {
                _set.GetObjectData(info, context);
            }
        }

        private static void Main(string[] args)
        {
            HashQueue<int> queue = new HashQueue<int>(5);
            queue.Add(1);
            queue.Add(2);
            queue.Add(3);
            queue.Add(4);
            queue.Add(5);
            queue.Add(6);
            queue.ProcessItems((i) => Console.Write(i));
            //foreach (int i in queue)
            //{
            //    Console.Write("{0}", i);
            //}
        }
    }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文