C#中高效向集合添加数值范围仅替换null元素的实现方案
实现需求的.NET内置结构方案
完全可以用.NET内置数据结构实现这个AddRange方法,核心是通过预跟踪空位索引避免遍历集合查找空位,同时用数组存储元素保证直接访问。以下是两种适配不同场景的实现方案:
方案1:按空位顺序填充(无需连续空位)
适合不要求添加的元素必须放在连续位置的场景,用Queue<int>存储所有空位的索引,初始化时将集合的所有索引入队,添加元素时直接从队列取出空位赋值,全程无需遍历集合找空位。
代码实现
public class NullReplaceableCollection<T> where T : struct { private readonly T?[] _elements; private readonly Queue<int> _emptySlotIndices; // 初始化指定容量的空集合 public NullReplaceableCollection(int capacity) { _elements = new T?[capacity]; _emptySlotIndices = new Queue<int>(Enumerable.Range(0, capacity)); } public bool AddRange(T[] values) { if (values == null || values.Length == 0) return false; // 空位不足直接返回false if (_emptySlotIndices.Count < values.Length) return false; // 依次取出空位填充元素 for (int i = 0; i < values.Length; i++) { int slotIndex = _emptySlotIndices.Dequeue(); _elements[slotIndex] = values[i]; } return true; } // 辅助方法:获取当前集合的副本 public T?[] GetCurrentState() => (T?[])_elements.Clone(); }
测试示例
- 初始化容量为6的集合,
GetCurrentState()返回{null,null,null,null,null,null} - 调用
AddRange(new int[]{2,3,4}),返回true,集合变为{2,3,4,null,null,null} - 再调用
AddRange(new int[]{0,1,5}),返回true,集合被填满 - 调用
AddRange(new int[]{4,5}),因无空位返回false
方案2:强制连续空位填充
如果要求添加的元素必须放在连续的空位区间(匹配你示例中填充中间三个空位的场景),可以用SortedSet<int>存储空位索引,利用其有序性快速查找连续的空位区间,同样无需遍历整个集合。
代码实现
public class ContinuousNullReplaceableCollection<T> where T : struct { private readonly T?[] _elements; private readonly SortedSet<int> _emptySlotIndices; public ContinuousNullReplaceableCollection(int capacity) { _elements = new T?[capacity]; _emptySlotIndices = new SortedSet<int>(Enumerable.Range(0, capacity)); } public bool AddRange(T[] values) { if (values == null || values.Length == 0) return false; int requiredSlots = values.Length; if (_emptySlotIndices.Count < requiredSlots) return false; // 查找连续的requiredSlots个空位 int? startSlot = null; foreach (var slot in _emptySlotIndices) { bool hasConsecutive = true; for (int i = 1; i < requiredSlots; i++) { if (!_emptySlotIndices.Contains(slot + i)) { hasConsecutive = false; break; } } if (hasConsecutive) { startSlot = slot; break; } } // 找不到连续空位则返回false if (startSlot == null) return false; // 填充连续空位 for (int i = 0; i < requiredSlots; i++) { int slotIndex = startSlot.Value + i; _emptySlotIndices.Remove(slotIndex); _elements[slotIndex] = values[i]; } return true; } public T?[] GetCurrentState() => (T?[])_elements.Clone(); }
关键优势
两种方案都完全避免了遍历集合查找空位的操作:
Queue<int>直接缓存所有空位索引,取用时O(1)SortedSet<int>利用有序性快速定位连续区间,无需遍历整个集合- 所有操作都是基于数组的直接索引访问,性能高效
内容的提问来源于stack exchange,提问作者user1423893
相关产品推荐
相关产品推荐

