Add IReadOnlyCollection AddRange overload

This commit is contained in:
Marek Lemańczyk committed 2025-09-16 13:52:42 +02:00
1 parent 050d7fd386
commit f6640deaf1
2 files changed
+103

No files matched your search

@@ -1108,6 +1108,53 @@ namespace Recyclable.Collections
}
}
[MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.AggressiveOptimization)]
internal static void AddRange<T>(this RecyclablePriorityQueue<T> queue, IReadOnlyCollection<T> items)
{
int count = items.Count;
if (count == 0)
{
return;
}
int startIndex = queue._size;
int newCount = startIndex + count;
EnsureCapacity(queue, newCount);
int index = startIndex;
foreach (T item in items)
{
queue._heap[index++] = item;
}
queue._size = newCount;
int half = newCount >> 1;
for (int i = half - 1; i >= 0; i--)
{
int idx = i;
T current = queue._heap[idx];
while (idx < half)
{
int child = (idx << 1) + 1;
int right = child + 1;
if (right < newCount && queue._comparer.Compare(queue._heap[right], queue._heap[child]) < 0)
{
child = right;
}
if (queue._comparer.Compare(queue._heap[child], current) >= 0)
{
break;
}
queue._heap[idx] = queue._heap[child];
idx = child;
}
queue._heap[idx] = current;
}
}
[MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.AggressiveOptimization)]
internal static IEnumerator AddRange<T>(this RecyclablePriorityQueue<T> queue, IEnumerable source)
{
@@ -1178,6 +1225,10 @@ namespace Recyclable.Collections
{
AddRange(queue, readOnlyList);
}
else if (items is IReadOnlyCollection<T> readOnlyCollection)
{
AddRange(queue, readOnlyCollection);
}
else
{
foreach (T item in items)
@@ -1,5 +1,6 @@
using FluentAssertions;
using Recyclable.Collections;
using System.Collections;
namespace Recyclable.CollectionsTests
{
@@ -406,6 +407,57 @@ namespace Recyclable.CollectionsTests
_ = result.Should().Equal(expected);
}
[Fact]
public void AddRangeReadOnlyCollectionShouldAddItemsInSortedOrder()
{
var source = new TestReadOnlyCollection<int>(_testData);
using var queue = new RecyclablePriorityQueue<int>();
queue.AddRange(source);
var result = new List<int>();
while (queue.LongCount > 0)
{
result.Add(queue.Dequeue());
}
_ = result.Should().Equal(_testData.Order());
}
[Fact]
public void AddRangeReadOnlyCollectionShouldNotOverrideItems()
{
var source = new TestReadOnlyCollection<int>(_testData);
using var queue = new RecyclablePriorityQueue<int>();
queue.AddRange(source);
queue.AddRange(source);
var expected = _testData.Concat(_testData).Order().ToArray();
var result = new List<int>();
while (queue.LongCount > 0)
{
result.Add(queue.Dequeue());
}
_ = result.Should().Equal(expected);
}
private sealed class TestReadOnlyCollection<T> : IReadOnlyCollection<T>
{
private readonly T[] _items;
public TestReadOnlyCollection(T[] items)
{
_items = items;
}
public int Count => _items.Length;
public IEnumerator<T> GetEnumerator() => ((IEnumerable<T>)_items).GetEnumerator();
IEnumerator IEnumerable.GetEnumerator() => _items.GetEnumerator();
}
}
}