208 lines
6.5 KiB
C#
208 lines
6.5 KiB
C#
using System;
|
||
using System.Collections.Generic;
|
||
using NBC.Pool;
|
||
|
||
#pragma warning disable CS8600 // Converting null literal or possible null value to non-nullable type.
|
||
|
||
namespace NBC.DataStructure.Collection
|
||
{
|
||
/// <summary>
|
||
/// 一对多哈希集合(OneToManyHashSet)对象池。
|
||
/// </summary>
|
||
/// <typeparam name="TKey">键的类型。</typeparam>
|
||
/// <typeparam name="TValue">值的类型。</typeparam>
|
||
public class OneToManyHashSetPool<TKey, TValue> : OneToManyHashSet<TKey, TValue>, IDisposable, IPool where TKey : notnull
|
||
{
|
||
private bool _isPool;
|
||
private bool _isDispose;
|
||
|
||
/// <summary>
|
||
/// 创建一个 <see cref="OneToManyHashSetPool{TKey, TValue}"/> 一对多哈希集合(OneToManyHashSet)对象池的实例。
|
||
/// </summary>
|
||
/// <returns>创建的实例。</returns>
|
||
public static OneToManyHashSetPool<TKey, TValue> Create()
|
||
{
|
||
#if FANTASY_WEBGL
|
||
var a = Pool<OneToManyHashSetPool<TKey, TValue>>.Rent();
|
||
#else
|
||
var a = MultiThreadPool.Rent<OneToManyHashSetPool<TKey, TValue>>();
|
||
#endif
|
||
a._isDispose = false;
|
||
a._isPool = true;
|
||
return a;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 释放实例所占用的资源,并将实例返回到对象池中,以便重用。
|
||
/// </summary>
|
||
public void Dispose()
|
||
{
|
||
if (_isDispose)
|
||
{
|
||
return;
|
||
}
|
||
|
||
_isDispose = true;
|
||
Clear();
|
||
#if FANTASY_WEBGL
|
||
Pool<OneToManyHashSetPool<TKey, TValue>>.Return(this);
|
||
#else
|
||
MultiThreadPool.Return(this);
|
||
#endif
|
||
}
|
||
|
||
/// <summary>
|
||
/// 获取一个值,该值指示当前实例是否为对象池中的实例。
|
||
/// </summary>
|
||
/// <returns></returns>
|
||
public bool IsPool()
|
||
{
|
||
return _isPool;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 设置一个值,该值指示当前实例是否为对象池中的实例。
|
||
/// </summary>
|
||
/// <param name="isPool"></param>
|
||
public void SetIsPool(bool isPool)
|
||
{
|
||
_isPool = isPool;
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 一对多哈希集合(OneToManyHashSet),用于创建和管理键对应多个值的集合。
|
||
/// </summary>
|
||
/// <typeparam name="TKey">键的类型。</typeparam>
|
||
/// <typeparam name="TValue">值的类型。</typeparam>
|
||
public class OneToManyHashSet<TKey, TValue> : Dictionary<TKey, HashSet<TValue>> where TKey : notnull
|
||
{
|
||
/// 用于回收和重用的空闲值集合队列。
|
||
private readonly Queue<HashSet<TValue>> _queue = new Queue<HashSet<TValue>>();
|
||
/// 设置最大回收限制,用于控制值集合的最大数量。
|
||
private readonly int _recyclingLimit = 120;
|
||
/// 一个空的、不包含任何元素的哈希集合,用于在查找失败时返回。
|
||
private static HashSet<TValue> _empty = new HashSet<TValue>();
|
||
|
||
/// <summary>
|
||
/// 初始化 <see cref="OneToManyHashSet{TKey, TValue}"/> 类的新实例。
|
||
/// </summary>
|
||
public OneToManyHashSet() { }
|
||
|
||
/// <summary>
|
||
/// 设置最大缓存数量
|
||
/// </summary>
|
||
/// <param name="recyclingLimit">
|
||
/// 1:防止数据量过大、所以超过recyclingLimit的数据还是走GC.
|
||
/// 2:设置成0不控制数量,全部缓存
|
||
/// </param>
|
||
public OneToManyHashSet(int recyclingLimit)
|
||
{
|
||
_recyclingLimit = recyclingLimit;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 判断指定的键值对是否存在于集合中。
|
||
/// </summary>
|
||
/// <param name="key">键。</param>
|
||
/// <param name="value">值。</param>
|
||
/// <returns>如果存在则为 true,否则为 false。</returns>
|
||
public bool Contains(TKey key, TValue value)
|
||
{
|
||
TryGetValue(key, out var list);
|
||
|
||
return list != null && list.Contains(value);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 添加指定的键值对到集合中。
|
||
/// </summary>
|
||
/// <param name="key">键。</param>
|
||
/// <param name="value">值。</param>
|
||
public void Add(TKey key, TValue value)
|
||
{
|
||
if (!TryGetValue(key, out var list))
|
||
{
|
||
list = Fetch();
|
||
list.Add(value);
|
||
Add(key, list);
|
||
|
||
return;
|
||
}
|
||
|
||
list.Add(value);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 从集合中移除指定键对应的值。
|
||
/// </summary>
|
||
/// <param name="key">键。</param>
|
||
/// <param name="value">要移除的值。</param>
|
||
public void RemoveValue(TKey key, TValue value)
|
||
{
|
||
if (!TryGetValue(key, out var list)) return;
|
||
|
||
list.Remove(value);
|
||
|
||
if (list.Count == 0) RemoveKey(key);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 从集合中移除指定键及其对应的值集合。
|
||
/// </summary>
|
||
/// <param name="key">键。</param>
|
||
public void RemoveKey(TKey key)
|
||
{
|
||
if (!TryGetValue(key, out var list)) return;
|
||
|
||
Remove(key);
|
||
Recycle(list);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 获取指定键对应的值集合,如果不存在则返回一个空的哈希集合。
|
||
/// </summary>
|
||
/// <param name="key">键。</param>
|
||
/// <returns>对应的值集合或空的哈希集合。</returns>
|
||
public HashSet<TValue> GetValue(TKey key)
|
||
{
|
||
if (TryGetValue(key, out HashSet<TValue> value))
|
||
{
|
||
return value;
|
||
}
|
||
|
||
return _empty;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 从队列中获取一个空闲的值集合,或者创建一个新的。
|
||
/// </summary>
|
||
/// <returns>值集合。</returns>
|
||
private HashSet<TValue> Fetch()
|
||
{
|
||
return _queue.Count <= 0 ? new HashSet<TValue>() : _queue.Dequeue();
|
||
}
|
||
|
||
/// <summary>
|
||
/// 回收值集合到队列中,以便重复利用。
|
||
/// </summary>
|
||
/// <param name="list">要回收的值集合。</param>
|
||
private void Recycle(HashSet<TValue> list)
|
||
{
|
||
list.Clear();
|
||
|
||
if (_recyclingLimit != 0 && _queue.Count > _recyclingLimit) return;
|
||
|
||
_queue.Enqueue(list);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 清空集合中的数据并和队列。
|
||
/// </summary>
|
||
protected new void Clear()
|
||
{
|
||
base.Clear();
|
||
_queue.Clear();
|
||
}
|
||
}
|
||
} |