.NET似乎有很多数据结构和集合类型。它是否具有最大尺寸且没有重复的先进先出集合,或类似的东西?
示例用法类似于存储5个最近打开的文件。如果添加了第6个对象,则将最近的对象出列以使大小保持为5
答案 0 :(得分:3)
您必须创建一个QueueSet
来实现ICollection<T>
。它可以是包含集合作为后备存储的包装类。它可以实现如下:
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();
}
}
我将此代码发布到公共领域。
答案 1 :(得分:1)
你想要一个queue,不是吗?
它实际上不支持最大大小而且没有重复,但您可以从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
}
答案 2 :(得分:0)
看看这个:Limit size of Queue<T> in .NET?
你基本上需要一个Queue
,如果你设法限制它的大小并让它“索引”或“唯一”那么你就可以了:)
我相信Dictionary
周围的一些逻辑也会起作用,您将存储的数据类型是什么?字符串?
答案 3 :(得分:0)
这是您想要的, HashQueue<T>
,哈希排队集。
添加了一些线程锁,防止意外锁定。请记住,所有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);
//}
}
}
}