// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。
//
// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。
//
// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
namespace Admin.NET.Core;
///
/// 队列扩展方法
///
public static class QueueExtensions
{
///
/// 批量入队
///
/// 队列元素类型
/// 队列实例
/// 要入队的元素集合
/// 队列或元素集合为空时抛出
public static void EnqueueRange(this Queue queue, IEnumerable items)
{
ArgumentNullException.ThrowIfNull(queue);
ArgumentNullException.ThrowIfNull(items);
foreach (var item in items)
{
queue.Enqueue(item);
}
}
///
/// 批量出队
///
/// 队列元素类型
/// 队列实例
/// 要出队的元素数量
/// 出队的元素集合
/// 队列为空时抛出
/// 数量小于0或大于队列长度时抛出
public static IEnumerable DequeueRange(this Queue queue, int count)
{
ArgumentNullException.ThrowIfNull(queue);
if (count < 0)
{
throw new ArgumentOutOfRangeException(nameof(count), "数量不能小于0");
}
if (count > queue.Count)
{
throw new ArgumentOutOfRangeException(nameof(count), "数量不能大于队列长度");
}
var result = new List(count);
for (var i = 0; i < count; i++)
{
result.Add(queue.Dequeue());
}
return result;
}
///
/// 尝试出队多个元素
///
/// 队列元素类型
/// 队列实例
/// 要出队的元素数量
/// 出队的元素集合
/// 是否成功出队指定数量的元素
public static bool TryDequeueRange(this Queue queue, int count, out IEnumerable items)
{
items = [];
if (count < 0 || count > queue.Count)
{
return false;
}
var result = new List(count);
for (var i = 0; i < count; i++)
{
if (queue.TryDequeue(out var item))
{
result.Add(item);
}
else
{
// 恢复已出队的元素
foreach (var restoredItem in result.AsEnumerable().Reverse())
{
var tempQueue = new Queue();
tempQueue.Enqueue(restoredItem);
while (queue.Count > 0)
{
tempQueue.Enqueue(queue.Dequeue());
}
while (tempQueue.Count > 0)
{
queue.Enqueue(tempQueue.Dequeue());
}
}
return false;
}
}
items = result;
return true;
}
///
/// 清空队列并返回所有元素
///
/// 队列元素类型
/// 队列实例
/// 队列中的所有元素
/// 队列为空时抛出
public static IEnumerable DrainToList(this Queue queue)
{
ArgumentNullException.ThrowIfNull(queue);
var result = new List(queue.Count);
while (queue.Count > 0)
{
result.Add(queue.Dequeue());
}
return result;
}
///
/// 安全地查看队列头部元素
///
/// 队列元素类型
/// 队列实例
/// 队列头部元素
/// 是否成功查看
public static bool TryPeek(this Queue queue, out T? item)
{
item = default;
if (queue.Count == 0)
{
return false;
}
item = queue.Peek();
return true;
}
///
/// 检查队列是否为空
///
/// 队列元素类型
/// 队列实例
/// 队列是否为空
public static bool IsEmpty(this Queue queue)
{
return queue?.Count == 0;
}
///
/// 检查队列是否不为空
///
/// 队列元素类型
/// 队列实例
/// 队列是否不为空
public static bool IsNotEmpty(this Queue queue)
{
return queue?.Count > 0;
}
///
/// 将队列转换为数组
///
/// 队列元素类型
/// 队列实例
/// 包含队列所有元素的数组
/// 队列为空时抛出
public static T[] ToArrayPreserveOrder(this Queue queue)
{
ArgumentNullException.ThrowIfNull(queue);
return [.. queue];
}
///
/// 复制队列
///
/// 队列元素类型
/// 原队列
/// 复制的新队列
/// 队列为空时抛出
public static Queue Clone(this Queue queue)
{
ArgumentNullException.ThrowIfNull(queue);
return new Queue(queue);
}
///
/// 查找队列中是否包含满足条件的元素
///
/// 队列元素类型
/// 队列实例
/// 匹配条件
/// 是否包含满足条件的元素
/// 队列或条件为空时抛出
public static bool Contains(this Queue queue, Func predicate)
{
ArgumentNullException.ThrowIfNull(queue);
ArgumentNullException.ThrowIfNull(predicate);
return queue.Any(predicate);
}
///
/// 统计队列中满足条件的元素数量
///
/// 队列元素类型
/// 队列实例
/// 匹配条件
/// 满足条件的元素数量
/// 队列或条件为空时抛出
public static int Count(this Queue queue, Func predicate)
{
ArgumentNullException.ThrowIfNull(queue);
ArgumentNullException.ThrowIfNull(predicate);
return queue.Count(predicate);
}
///
/// 对队列中的每个元素执行指定操作
///
/// 队列元素类型
/// 队列实例
/// 要执行的操作
/// 队列或操作为空时抛出
public static void ForEach(this Queue queue, Action action)
{
ArgumentNullException.ThrowIfNull(queue);
ArgumentNullException.ThrowIfNull(action);
foreach (var item in queue)
{
action(item);
}
}
///
/// 对队列中的每个元素执行指定操作(带索引)
///
/// 队列元素类型
/// 队列实例
/// 要执行的操作,参数为元素和索引
/// 队列或操作为空时抛出
public static void ForEach(this Queue queue, Action action)
{
ArgumentNullException.ThrowIfNull(queue);
ArgumentNullException.ThrowIfNull(action);
var index = 0;
foreach (var item in queue)
{
action(item, index++);
}
}
///
/// 创建一个新队列,包含满足条件的元素
///
/// 队列元素类型
/// 原队列
/// 筛选条件
/// 包含满足条件元素的新队列
/// 队列或条件为空时抛出
public static Queue Where(this Queue queue, Func predicate)
{
ArgumentNullException.ThrowIfNull(queue);
ArgumentNullException.ThrowIfNull(predicate);
var result = new Queue();
foreach (var item in queue.Where(predicate))
{
result.Enqueue(item);
}
return result;
}
///
/// 创建一个新队列,包含转换后的元素
///
/// 原队列元素类型
/// 目标队列元素类型
/// 原队列
/// 转换函数
/// 包含转换后元素的新队列
/// 队列或转换函数为空时抛出
public static Queue Select(this Queue queue, Func selector)
{
ArgumentNullException.ThrowIfNull(queue);
ArgumentNullException.ThrowIfNull(selector);
var result = new Queue();
foreach (var item in queue.Select(selector))
{
result.Enqueue(item);
}
return result;
}
///
/// 限制队列的最大长度,超出时移除最旧的元素
///
/// 队列元素类型
/// 队列实例
/// 最大长度
/// 队列为空时抛出
/// 最大长度小于0时抛出
public static void LimitSize(this Queue queue, int maxSize)
{
ArgumentNullException.ThrowIfNull(queue);
if (maxSize < 0)
{
throw new ArgumentOutOfRangeException(nameof(maxSize), "最大长度不能小于0");
}
while (queue.Count > maxSize)
{
queue.Dequeue();
}
}
///
/// 安全地入队元素,如果队列已满则移除最旧的元素
///
/// 队列元素类型
/// 队列实例
/// 要入队的元素
/// 队列最大长度
/// 被移除的元素(如果有)
/// 队列为空时抛出
/// 最大长度小于1时抛出
public static T? EnqueueWithLimit(this Queue queue, T item, int maxSize)
{
ArgumentNullException.ThrowIfNull(queue);
if (maxSize < 1)
{
throw new ArgumentOutOfRangeException(nameof(maxSize), "最大长度不能小于1");
}
T? removedItem = default;
if (queue.Count >= maxSize)
{
removedItem = queue.Dequeue();
}
queue.Enqueue(item);
return removedItem;
}
}