[corefx注释说]-System.Collections.Generic.Queue<T>
2015-07-09 01:31
525 查看
为了节省时间,只写一些关注的方法好了,剩下的可以MSDN嘛XD
首先是声明部分,表示为队列是一个可用于枚举的只读集合
这里有“递增因子”的概念存在,因此可以从中学习到对于队列这样的数据结构,通过使用数组,如何在“满队”情况下扩充空间。
提供三种构造方法:
构造空队列
构造指定空间容量的队列
复制已有队列(特别注意这个,很有意思)
这里没什么好说的,第一个是返回当前队列内的元素数,第二个是返回同步对象。
这里可以看出来,这里的队列使用的是“循环队列”的概念(_tail入 _head 出)。这里需要再次明确的是:_size是指的元素个数而非真实的数组长度(Array.Length)
复制到从某一索引起的指定的一个数组中。当然中间做了一些容量是否足够等等的判断
void Enqueue(T) 入队列
这里看一下“生长因子”的作用:就是个生长比例。。代码里跟Stack一样是两倍这样子往上加。这个强类型转换弄得整个人蒙蒙哒。
这里有个SetCapacity这个方法,这个方法的看点是如何解决从“环形队列”里抽取掉没用的数组单元。
这里很奇怪,退出队列时并没有检查是否空间过分冗余而作空间节省上的优化(实用阶段这一块不做是明智的吗?看来空间不值钱是趋势)
方法是这样的:把原来在_array中的所有元素,规规矩矩排好顺序(因为是循环队列,可能下标和队内顺序不是偏序嘛)然后再把_array 指向 newarray
但是这里并没有判断capacity和size的关系!(其实Copy会报异常的)
这里特意兴冲冲的跑去VS13实验一下:会引发目标长度不够。
异常发生点:
在 System.Array.Copy(Array sourceArray, Int32 sourceIndex, Array destinationArray, Int32 destinationIndex, Int32 length, Boolean reliable)
在 System.Collections.Generic.Queue`1.SetCapacity(Int32 capacity)
(看来还真的是还没开完,或者说是有新改进)
测试代码:
首先是声明部分,表示为队列是一个可用于枚举的只读集合
[DebuggerTypeProxy(typeof(QueueDebugView<>))] [DebuggerDisplay("Count = {Count}")] public class Queue<T> : IEnumerable<T>, System.Collections.ICollection, IReadOnlyCollection<T>
字段
private T[] _array; private int _head; // First valid element in the queue private int _tail; // Last valid element in the queue private int _size; // Number of elements. private int _version; private Object _syncRoot; private const int MinimumGrow = 4; private const int GrowFactor = 200; // double each time private const int DefaultCapacity = 4;
这里有“递增因子”的概念存在,因此可以从中学习到对于队列这样的数据结构,通过使用数组,如何在“满队”情况下扩充空间。
构造方法
// Creates a queue with room for capacity objects. The default initial // capacity and grow factor are used. /// <include file='doc\Queue.uex' path='docs/doc[@for="Queue.Queue"]/*' /> public Queue() { _array = Array.Empty<T>(); } // Creates a queue with room for capacity objects. The default grow factor // is used. // /// <include file='doc\Queue.uex' path='docs/doc[@for="Queue.Queue1"]/*' /> public Queue(int capacity) { if (capacity < 0) throw new ArgumentOutOfRangeException("capacity", SR.ArgumentOutOfRange_NeedNonNegNumRequired); _array = new T[capacity]; } // Fills a Queue with the elements of an ICollection. Uses the enumerator // to get each of the elements. // /// <include file='doc\Queue.uex' path='docs/doc[@for="Queue.Queue3"]/*' /> public Queue(IEnumerable<T> collection) { if (collection == null) throw new ArgumentNullException("collection"); _array = new T[DefaultCapacity]; using (IEnumerator<T> en = collection.GetEnumerator()) { while (en.MoveNext()) { Enqueue(en.Current); } } }
提供三种构造方法:
构造空队列
构造指定空间容量的队列
复制已有队列(特别注意这个,很有意思)
属性
/// <include file='doc\Queue.uex' path='docs/doc[@for="Queue.Count"]/*' /> public int Count { get { return _size; } } /// <include file='doc\Queue.uex' path='docs/doc[@for="Queue.IsSynchronized"]/*' /> bool System.Collections.ICollection.IsSynchronized { get { return false; } } Object System.Collections.ICollection.SyncRoot { get { if (_syncRoot == null) { System.Threading.Interlocked.CompareExchange<Object>(ref _syncRoot, new Object(), null); } return _syncRoot; } }
这里没什么好说的,第一个是返回当前队列内的元素数,第二个是返回同步对象。
方法
void Clear() //清除队列内所有元素
// Removes all Objects from the queue. /// <include file='doc\Queue.uex' path='docs/doc[@for="Queue.Clear"]/*' /> public void Clear() { if (_head < _tail) Array.Clear(_array, _head, _size); else { Array.Clear(_array, _head, _array.Length - _head); Array.Clear(_array, 0, _tail); } _head = 0; _tail = 0; _size = 0; _version++; }
这里可以看出来,这里的队列使用的是“循环队列”的概念(_tail入 _head 出)。这里需要再次明确的是:_size是指的元素个数而非真实的数组长度(Array.Length)
void CopyTo(T[], int) / void Copy(Array, int) 复制到某一数组中
// CopyTo copies a collection into an Array, starting at a particular // index into the array. // /// <include file='doc\Queue.uex' path='docs/doc[@for="Queue.CopyTo"]/*' /> public void CopyTo(T[] array, int arrayIndex) { if (array == null) { throw new ArgumentNullException("array"); } if (arrayIndex < 0 || arrayIndex > array.Length) { throw new ArgumentOutOfRangeException("arrayIndex", SR.ArgumentOutOfRange_Index); } int arrayLen = array.Length; if (arrayLen - arrayIndex < _size) { throw new ArgumentException(SR.Argument_InvalidOffLen); } int numToCopy = (arrayLen - arrayIndex < _size) ? (arrayLen - arrayIndex) : _size; if (numToCopy == 0) return; int firstPart = (_array.Length - _head < numToCopy) ? _array.Length - _head : numToCopy; Array.Copy(_array, _head, array, arrayIndex, firstPart); numToCopy -= firstPart; if (numToCopy > 0) { Array.Copy(_array, 0, array, arrayIndex + _array.Length - _head, numToCopy); } } void System.Collections.ICollection.CopyTo(Array array, int index) { if (array == null) { throw new ArgumentNullException("array"); } if (array.Rank != 1) { throw new ArgumentException(SR.Arg_RankMultiDimNotSupported); } if (array.GetLowerBound(0) != 0) { throw new ArgumentException(SR.Arg_NonZeroLowerBound); } int arrayLen = array.Length; if (index < 0 || index > arrayLen) { throw new ArgumentOutOfRangeException("index", SR.ArgumentOutOfRange_Index); } if (arrayLen - index < _size) { throw new ArgumentException(SR.Argument_InvalidOffLen); } int numToCopy = (arrayLen - index < _size) ? arrayLen - index : _size; if (numToCopy == 0) return; try { int firstPart = (_array.Length - _head < numToCopy) ? _array.Length - _head : numToCopy; Array.Copy(_array, _head, array, index, firstPart); numToCopy -= firstPart; if (numToCopy > 0) { Array.Copy(_array, 0, array, index + _array.Length - _head, numToCopy); } } catch (ArrayTypeMismatchException) { throw new ArgumentException(SR.Argument_InvalidArrayType); }
复制到从某一索引起的指定的一个数组中。当然中间做了一些容量是否足够等等的判断
void Enqueue(T) 入队列
// Adds item to the tail of the queue. // /// <include file='doc\Queue.uex' path='docs/doc[@for="Queue.Enqueue"]/*' /> public void Enqueue(T item) { if (_size == _array.Length) { int newcapacity = (int)((long)_array.Length * (long)GrowFactor / 100); if (newcapacity < _array.Length + MinimumGrow) { newcapacity = _array.Length + MinimumGrow; } SetCapacity(newcapacity); } _array[_tail] = item; _tail = (_tail + 1) % _array.Length; _size++; _version++; }
这里看一下“生长因子”的作用:就是个生长比例。。代码里跟Stack一样是两倍这样子往上加。这个强类型转换弄得整个人蒙蒙哒。
这里有个SetCapacity这个方法,这个方法的看点是如何解决从“环形队列”里抽取掉没用的数组单元。
T Dequeue() //出队列
public T Dequeue() { if (_size == 0) throw new InvalidOperationException(SR.InvalidOperation_EmptyQueue); T removed = _array[_head]; _array[_head] = default(T); _head = (_head + 1) % _array.Length; _size--; _version++; return removed; }
这里很奇怪,退出队列时并没有检查是否空间过分冗余而作空间节省上的优化(实用阶段这一块不做是明智的吗?看来空间不值钱是趋势)
T Peek() //队尾元素
public T Peek() { if (_size == 0) throw new InvalidOperationException(SR.InvalidOperation_EmptyQueue); return _array[_head]; }
bool Contains(T) 集合中是否存在某元素
public bool Contains(T item) { int index = _head; int count = _size; EqualityComparer<T> c = EqualityComparer<T>.Default; while (count-- > 0) { if (((Object)item) == null) { if (((Object)_array[index]) == null) return true; } else if (_array[index] != null && c.Equals(_array[index], item)) { return true; } index = (index + 1) % _array.Length; } return false; }
void SetCapacity(int) 设置队列容量
// PRIVATE Grows or shrinks the buffer to hold capacity objects. Capacity // must be >= _size. private void SetCapacity(int capacity) { T[] newarray = new T[capacity]; if (_size > 0) { if (_head < _tail) { Array.Copy(_array, _head, newarray, 0, _size); } else { Array.Copy(_array, _head, newarray, 0, _array.Length - _head); Array.Copy(_array, 0, newarray, _array.Length - _head, _tail); } } _array = newarray; _head = 0; _tail = (_size == capacity) ? 0 : _size; _version++; }
方法是这样的:把原来在_array中的所有元素,规规矩矩排好顺序(因为是循环队列,可能下标和队内顺序不是偏序嘛)然后再把_array 指向 newarray
但是这里并没有判断capacity和size的关系!(其实Copy会报异常的)
这里特意兴冲冲的跑去VS13实验一下:会引发目标长度不够。
异常发生点:
在 System.Array.Copy(Array sourceArray, Int32 sourceIndex, Array destinationArray, Int32 destinationIndex, Int32 length, Boolean reliable)
在 System.Collections.Generic.Queue`1.SetCapacity(Int32 capacity)
(看来还真的是还没开完,或者说是有新改进)
测试代码:
Queue<Int32> que = new Queue<int>(1024); for (int i = 0; i < 1023; i++) { que.Enqueue(i); } var dd = que.GetType().GetMethod("SetCapacity", BindingFlags.NonPublic | BindingFlags.Instance); dd.Invoke(que, new Object[] { 100 }); Console.ReadKey();
相关文章推荐
- 基础类型封装成NSNumber,NSValue和NSData后存储到NSArray/NSDictionary
- roboguice2教程
- Jdbcutls介绍
- POJ 2299 Ultra-QuickSort(树状数组)
- iOS UILabel根据字符串长度自动适应宽度和高度
- Serializable接口中serialVersionUID字段的作用
- 解决无法make uImage的问题
- 《开源框架那些事儿22》:UI框架设计实战
- iOS开发-UINavigationBar和Status Bar实用技巧
- iOS动力学UIDynamic讲解(二)
- iOS8 UILocalNotification 增加启动授权
- iOS8 UILocalNotification 增加启动授权
- 《开源框架那些事儿22》:UI框架设计实战
- Arduino 2048 游戏
- iOS [UIScreen mainScreen].bounds 获取屏幕大小不对的问题
- iOS开发-UI 从入门到精通(四)
- WinRT中如何快速获取Uri地址中的QueryString键值对信息
- UI的Title
- Permutation Sequence
- Gym 100548A Built with Qinghuai and Ari Factor (Asia Xian)