456 lines
14 KiB
C#
456 lines
14 KiB
C#
using System;
|
||
using System.Collections;
|
||
using System.Collections.Generic;
|
||
using System.Runtime.InteropServices;
|
||
|
||
namespace Convention.Collections
|
||
{
|
||
namespace Generic
|
||
{
|
||
/// <summary>
|
||
/// 附带有缓存机制的链表类
|
||
/// </summary>
|
||
/// <typeparam name="T">指定链表的元素类型</typeparam>
|
||
public sealed class LinkedCacheList<T> : ICollection<T>, IEnumerable<T>, ICollection, IEnumerable
|
||
{
|
||
private readonly LinkedList<T> m_LinkedList;
|
||
/// <summary>
|
||
/// 之所以需要这套缓存机制,主要有三点好处:
|
||
/// <list type="bullet">减少 GC 压力:大量频繁的插入/删除会产生很多短生命周期的节点对象,通过复用可以显著降低托管堆的分配与回收次数</list>
|
||
/// <list type="bullet">提升性能:避免频繁 new 和 GC,能减少停顿时间,提高链表在高频操作场景下的吞吐</list>
|
||
/// <list type="bullet">便于观察与管理:类中还提供了 CachedNodeCount 方便调试统计缓存规模,必要时可通过 ClearCachedNodes 主动释放</list>
|
||
/// 适用场景是节点使用模式“高频增删但总量有限”,此时缓存能稳定性能;若链表规模始终在增长且很少释放,缓存收益会较低。
|
||
/// </summary>
|
||
private readonly Queue<LinkedListNode<T>> m_CachedNodes;
|
||
|
||
/// <summary>
|
||
/// 初始化游戏框架链表类的新实例
|
||
/// </summary>
|
||
public LinkedCacheList()
|
||
{
|
||
m_LinkedList = new LinkedList<T>();
|
||
m_CachedNodes = new Queue<LinkedListNode<T>>();
|
||
}
|
||
|
||
/// <summary>
|
||
/// 获取链表中实际包含的结点数量
|
||
/// </summary>
|
||
public int Count
|
||
{
|
||
get
|
||
{
|
||
return m_LinkedList.Count;
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 获取链表结点缓存数量
|
||
/// </summary>
|
||
public int CachedNodeCount
|
||
{
|
||
get
|
||
{
|
||
return m_CachedNodes.Count;
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 获取链表的第一个结点
|
||
/// </summary>
|
||
public LinkedListNode<T> First
|
||
{
|
||
get
|
||
{
|
||
return m_LinkedList.First;
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 获取链表的最后一个结点
|
||
/// </summary>
|
||
public LinkedListNode<T> Last
|
||
{
|
||
get
|
||
{
|
||
return m_LinkedList.Last;
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 获取一个值,该值指示 <see cref="ICollection{T}"/> 是否为只读
|
||
/// </summary>
|
||
public bool IsReadOnly
|
||
{
|
||
get
|
||
{
|
||
return ((ICollection<T>)m_LinkedList).IsReadOnly;
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 获取可用于同步对 <see cref="ICollection"/> 的访问的对象。
|
||
/// </summary>
|
||
public object SyncRoot
|
||
{
|
||
get
|
||
{
|
||
return ((ICollection)m_LinkedList).SyncRoot;
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 获取一个值,该值指示是否同步对 <see cref="ICollection"/> 的访问(线程安全)。
|
||
/// </summary>
|
||
public bool IsSynchronized
|
||
{
|
||
get
|
||
{
|
||
return ((ICollection)m_LinkedList).IsSynchronized;
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 在链表中指定的现有结点后添加包含指定值的新结点
|
||
/// </summary>
|
||
/// <param name="node">指定的现有结点</param>
|
||
/// <param name="value">指定值</param>
|
||
/// <returns>包含指定值的新结点</returns>
|
||
public LinkedListNode<T> AddAfter(LinkedListNode<T> node, T value)
|
||
{
|
||
LinkedListNode<T> newNode = AcquireNode(value);
|
||
m_LinkedList.AddAfter(node, newNode);
|
||
return newNode;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 在链表中指定的现有结点后添加指定的新结点
|
||
/// </summary>
|
||
/// <param name="node">指定的现有结点</param>
|
||
/// <param name="newNode">指定的新结点</param>
|
||
public void AddAfter(LinkedListNode<T> node, LinkedListNode<T> newNode)
|
||
{
|
||
m_LinkedList.AddAfter(node, newNode);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 在链表中指定的现有结点前添加包含指定值的新结点
|
||
/// </summary>
|
||
/// <param name="node">指定的现有结点</param>
|
||
/// <param name="value">指定值</param>
|
||
/// <returns>包含指定值的新结点</returns>
|
||
public LinkedListNode<T> AddBefore(LinkedListNode<T> node, T value)
|
||
{
|
||
LinkedListNode<T> newNode = AcquireNode(value);
|
||
m_LinkedList.AddBefore(node, newNode);
|
||
return newNode;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 在链表中指定的现有结点前添加指定的新结点
|
||
/// </summary>
|
||
/// <param name="node">指定的现有结点</param>
|
||
/// <param name="newNode">指定的新结点</param>
|
||
public void AddBefore(LinkedListNode<T> node, LinkedListNode<T> newNode)
|
||
{
|
||
m_LinkedList.AddBefore(node, newNode);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 在链表的开头处添加包含指定值的新结点
|
||
/// </summary>
|
||
/// <param name="value">指定值</param>
|
||
/// <returns>包含指定值的新结点</returns>
|
||
public LinkedListNode<T> AddFirst(T value)
|
||
{
|
||
LinkedListNode<T> node = AcquireNode(value);
|
||
m_LinkedList.AddFirst(node);
|
||
return node;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 在链表的开头处添加指定的新结点
|
||
/// </summary>
|
||
/// <param name="node">指定的新结点</param>
|
||
public void AddFirst(LinkedListNode<T> node)
|
||
{
|
||
m_LinkedList.AddFirst(node);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 在链表的结尾处添加包含指定值的新结点
|
||
/// </summary>
|
||
/// <param name="value">指定值</param>
|
||
/// <returns>包含指定值的新结点</returns>
|
||
public LinkedListNode<T> AddLast(T value)
|
||
{
|
||
LinkedListNode<T> node = AcquireNode(value);
|
||
m_LinkedList.AddLast(node);
|
||
return node;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 在链表的结尾处添加指定的新结点
|
||
/// </summary>
|
||
/// <param name="node">指定的新结点</param>
|
||
public void AddLast(LinkedListNode<T> node)
|
||
{
|
||
m_LinkedList.AddLast(node);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 从链表中移除所有结点
|
||
/// </summary>
|
||
public void Clear()
|
||
{
|
||
LinkedListNode<T> current = m_LinkedList.First;
|
||
while (current != null)
|
||
{
|
||
ReleaseNode(current);
|
||
current = current.Next;
|
||
}
|
||
|
||
m_LinkedList.Clear();
|
||
}
|
||
|
||
/// <summary>
|
||
/// 清除链表结点缓存
|
||
/// </summary>
|
||
public void ClearCachedNodes()
|
||
{
|
||
m_CachedNodes.Clear();
|
||
}
|
||
|
||
/// <summary>
|
||
/// 确定某值是否在链表中
|
||
/// </summary>
|
||
/// <param name="value">指定值</param>
|
||
/// <returns>某值是否在链表中</returns>
|
||
public bool Contains(T value)
|
||
{
|
||
return m_LinkedList.Contains(value);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 从目标数组的指定索引处开始将整个链表复制到兼容的一维数组
|
||
/// </summary>
|
||
/// <param name="array">一维数组,它是从链表复制的元素的目标。数组必须具有从零开始的索引</param>
|
||
/// <param name="index">array 中从零开始的索引,从此处开始复制</param>
|
||
public void CopyTo(T[] array, int index)
|
||
{
|
||
m_LinkedList.CopyTo(array, index);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 从特定的 ICollection 索引开始,将数组的元素复制到一个数组中
|
||
/// </summary>
|
||
/// <param name="array">一维数组,它是从 ICollection 复制的元素的目标。数组必须具有从零开始的索引</param>
|
||
/// <param name="index">array 中从零开始的索引,从此处开始复制</param>
|
||
public void CopyTo(Array array, int index)
|
||
{
|
||
((ICollection)m_LinkedList).CopyTo(array, index);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 查找包含指定值的第一个结点
|
||
/// </summary>
|
||
/// <param name="value">要查找的指定值</param>
|
||
/// <returns>包含指定值的第一个结点</returns>
|
||
public LinkedListNode<T> Find(T value)
|
||
{
|
||
return m_LinkedList.Find(value);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 查找包含指定值的最后一个结点
|
||
/// </summary>
|
||
/// <param name="value">要查找的指定值</param>
|
||
/// <returns>包含指定值的最后一个结点</returns>
|
||
public LinkedListNode<T> FindLast(T value)
|
||
{
|
||
return m_LinkedList.FindLast(value);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 从链表中移除指定值的第一个匹配项
|
||
/// </summary>
|
||
/// <param name="value">指定值</param>
|
||
/// <returns>是否移除成功</returns>
|
||
public bool Remove(T value)
|
||
{
|
||
LinkedListNode<T> node = m_LinkedList.Find(value);
|
||
if (node != null)
|
||
{
|
||
m_LinkedList.Remove(node);
|
||
ReleaseNode(node);
|
||
return true;
|
||
}
|
||
|
||
return false;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 从链表中移除指定的结点
|
||
/// </summary>
|
||
/// <param name="node">指定的结点</param>
|
||
public void Remove(LinkedListNode<T> node)
|
||
{
|
||
m_LinkedList.Remove(node);
|
||
ReleaseNode(node);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 移除位于链表开头处的结点
|
||
/// </summary>
|
||
public void RemoveFirst()
|
||
{
|
||
LinkedListNode<T> first = m_LinkedList.First;
|
||
if (first == null)
|
||
{
|
||
throw new InvalidOperationException("Rmove first is invalid.");
|
||
}
|
||
|
||
m_LinkedList.RemoveFirst();
|
||
ReleaseNode(first);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 移除位于链表结尾处的结点。
|
||
/// </summary>
|
||
public void RemoveLast()
|
||
{
|
||
LinkedListNode<T> last = m_LinkedList.Last;
|
||
if (last == null)
|
||
{
|
||
throw new InvalidOperationException("Remove last is invalid.");
|
||
}
|
||
|
||
m_LinkedList.RemoveLast();
|
||
ReleaseNode(last);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 返回循环访问集合的枚举数
|
||
/// </summary>
|
||
/// <returns>循环访问集合的枚举数</returns>
|
||
public Enumerator GetEnumerator()
|
||
{
|
||
return new Enumerator(m_LinkedList);
|
||
}
|
||
|
||
private LinkedListNode<T> AcquireNode(T value)
|
||
{
|
||
LinkedListNode<T> node = null;
|
||
if (m_CachedNodes.Count > 0)
|
||
{
|
||
node = m_CachedNodes.Dequeue();
|
||
node.Value = value;
|
||
}
|
||
else
|
||
{
|
||
node = new LinkedListNode<T>(value);
|
||
}
|
||
|
||
return node;
|
||
}
|
||
|
||
private void ReleaseNode(LinkedListNode<T> node)
|
||
{
|
||
node.Value = default(T);
|
||
m_CachedNodes.Enqueue(node);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 将值添加到 ICollection`1 的结尾处
|
||
/// </summary>
|
||
/// <param name="value">要添加的值</param>
|
||
void ICollection<T>.Add(T value)
|
||
{
|
||
AddLast(value);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 返回循环访问集合的枚举数
|
||
/// </summary>
|
||
/// <returns>循环访问集合的枚举数</returns>
|
||
IEnumerator<T> IEnumerable<T>.GetEnumerator()
|
||
{
|
||
return GetEnumerator();
|
||
}
|
||
|
||
/// <summary>
|
||
/// 返回循环访问集合的枚举数
|
||
/// </summary>
|
||
/// <returns>循环访问集合的枚举数</returns>
|
||
IEnumerator IEnumerable.GetEnumerator()
|
||
{
|
||
return GetEnumerator();
|
||
}
|
||
|
||
/// <summary>
|
||
/// 循环访问集合的枚举数
|
||
/// </summary>
|
||
[StructLayout(LayoutKind.Auto)]
|
||
public struct Enumerator : IEnumerator<T>, IEnumerator
|
||
{
|
||
private LinkedList<T>.Enumerator m_Enumerator;
|
||
|
||
internal Enumerator(LinkedList<T> linkedList)
|
||
{
|
||
if (linkedList == null)
|
||
{
|
||
throw new InvalidOperationException("Linked list is invalid.");
|
||
}
|
||
|
||
m_Enumerator = linkedList.GetEnumerator();
|
||
}
|
||
|
||
/// <summary>
|
||
/// 获取当前结点
|
||
/// </summary>
|
||
public T Current
|
||
{
|
||
get
|
||
{
|
||
return m_Enumerator.Current;
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 获取当前的枚举数
|
||
/// </summary>
|
||
object IEnumerator.Current
|
||
{
|
||
get
|
||
{
|
||
return m_Enumerator.Current;
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 清理枚举数
|
||
/// </summary>
|
||
public void Dispose()
|
||
{
|
||
m_Enumerator.Dispose();
|
||
}
|
||
|
||
/// <summary>
|
||
/// 获取下一个结点
|
||
/// </summary>
|
||
/// <returns>返回下一个结点</returns>
|
||
public bool MoveNext()
|
||
{
|
||
return m_Enumerator.MoveNext();
|
||
}
|
||
|
||
/// <summary>
|
||
/// 重置枚举数
|
||
/// </summary>
|
||
void IEnumerator.Reset()
|
||
{
|
||
((IEnumerator<T>)m_Enumerator).Reset();
|
||
}
|
||
}
|
||
}
|
||
}
|
||
} |