.NET似乎有很多數據結構和集合類型。它是否具有最大尺寸和不重複的先進先出集合,或類似的東西?最大尺寸且不重複的先進先出集合?
一個示例用法就像存儲5個最近打開的文件一樣。如果添加第6個對象,則將最少的對象退出以將大小保持爲5
.NET似乎有很多數據結構和集合類型。它是否具有最大尺寸和不重複的先進先出集合,或類似的東西?最大尺寸且不重複的先進先出集合?
一個示例用法就像存儲5個最近打開的文件一樣。如果添加第6個對象,則將最少的對象退出以將大小保持爲5
您必須創建一個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();
}
}
我將此代碼發佈到公有領域。
一個評論,如果!queue.Contains(item),它應該重載該項目(使其成爲最近的一個) –
我假設你的意思是Enqueue方法應該將項目移動到隊列頂部,如果該項目已經存在在Enqueue被調用的隊列中,我是對的嗎? –
是的..這就是我的意思 –
您想要一個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);
}
}
含有或包裝或者已經-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
}
隊列允許重複並且沒有最大限制 –
實際上,從.NET中的內置集合繼承是不實際的。沒有任何有用的方法被聲明爲「虛擬」,因此它們不能被擴展。 –
@rtalbot:非通用版似乎工作,但延長'隊列
在這看看:Limit size of Queue<T> in .NET?
你基本上需要一個Queue
,如果你管理,以限制其大小,並把它「索引」或「唯一」,那麼你都OK了:)
我相信圍繞Dictionary
的一些邏輯也可以工作,你將存儲什麼數據類型?字符串?
在這種情況下,是的,一個字符串。如何限制隊列項目是唯一的? –
這就是你想要的,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);
//}
}
}
}
你有試過詞典,有排序能力嗎? –
添加排隊散列集的代碼示例 –
[如何在C#.NET中使用「FIFO」?](http://stackoverflow.com/questions/2966286/how-to-work-with-fifo- in-c-sharp-net) –