From e617541c31a75d832698f17dfe09adc173342121 Mon Sep 17 00:00:00 2001 From: mlemanczyk Date: Tue, 3 Jan 2023 00:42:43 +0100 Subject: [PATCH] RecyclableSortedList added --- .../Recyclable.Collections.csproj | 9 +- .../RecyclableSortedList.cs | 43 +++++++++ .../Recyclable.CollectionsTests.csproj | 6 +- .../RecyclableSortedListTests.cs | 88 +++++++++++++++++++ 4 files changed, 140 insertions(+), 6 deletions(-) create mode 100644 Recyclable.Collections/RecyclableSortedList.cs create mode 100644 Recyclable.CollectionsTests/RecyclableSortedListTests.cs diff --git a/Recyclable.Collections/Recyclable.Collections.csproj b/Recyclable.Collections/Recyclable.Collections.csproj index b29d18c..1be10da 100644 --- a/Recyclable.Collections/Recyclable.Collections.csproj +++ b/Recyclable.Collections/Recyclable.Collections.csproj @@ -15,10 +15,17 @@ Recyclable.Collections project is an open source framework for operating dynamic lists at performance close to raw arrays. It aims at providing high performance with minimal memory footprint. It implements IList<T>'s interface and is targeted as direct replacements of List<T>, SortableList<T>, PriorityQueue<T> and similar. The project & source code is free for educational, open-source & personal use. + https://github.com/mlemanczyk/Recyclable.Collections + https://github.com/mlemanczyk/Recyclable.Collections + Marek Lemańczyk 2023 + https://github.com/mlemanczyk/Recyclable.Collections + /README.md - + + PreserveNewest + diff --git a/Recyclable.Collections/RecyclableSortedList.cs b/Recyclable.Collections/RecyclableSortedList.cs new file mode 100644 index 0000000..78f3382 --- /dev/null +++ b/Recyclable.Collections/RecyclableSortedList.cs @@ -0,0 +1,43 @@ +namespace Recyclable.Collections +{ + public class RecyclableSortedList : RecyclableList<(TKey Key, TValue Value)> + where TKey : notnull + { + private static readonly IComparer<(TKey, TValue)> _comparer = new FrequencyTupleComparer(); + private readonly SystemRandomNumberGenerator _randomNumberGenerator = new SystemRandomNumberGenerator(); + + protected override void ListUpdated() + { + base.ListUpdated(); + QuickSort(); + } + + public RecyclableSortedList() : base() + { + } + + public RecyclableSortedList(Dictionary source, int blockSize = RecyclableDefaults.BlockSize) + : this(source.Select(x => (x.Key, x.Value)), blockSize) + { + } + + public RecyclableSortedList(IEnumerable<(TKey Key, TValue Value)> source, int blockSize = RecyclableDefaults.BlockSize) + : base(source, blockSize) + { + QuickSort(); + } + + public void QuickSort() + { + _isUpdating++; + try + { + this.QuickSort(_comparer, _randomNumberGenerator); + } + finally + { + _isUpdating--; + } + } + } +} diff --git a/Recyclable.CollectionsTests/Recyclable.CollectionsTests.csproj b/Recyclable.CollectionsTests/Recyclable.CollectionsTests.csproj index df55634..12982dd 100644 --- a/Recyclable.CollectionsTests/Recyclable.CollectionsTests.csproj +++ b/Recyclable.CollectionsTests/Recyclable.CollectionsTests.csproj @@ -1,4 +1,4 @@ - + net6.0 @@ -8,10 +8,6 @@ false - - - - diff --git a/Recyclable.CollectionsTests/RecyclableSortedListTests.cs b/Recyclable.CollectionsTests/RecyclableSortedListTests.cs new file mode 100644 index 0000000..0096f7f --- /dev/null +++ b/Recyclable.CollectionsTests/RecyclableSortedListTests.cs @@ -0,0 +1,88 @@ +using FluentAssertions; +using Recyclable.Collections; + +namespace Recyclable.CollectionsTests +{ + [TestClass()] + public class RecyclableSortedListTests + { + private static readonly (int, string)[] _testData = new[] { (5, "a"), (4, "d"), (3, "c"), (2, "b"), (1, "a") }; + + [TestMethod] + public void ShouldBeSortedWhenCreated() + { + // Act + using var sortedList = new RecyclableSortedList(_testData); + + // Validate + _ = sortedList.Should().HaveCount(_testData.Length) + .And.BeEquivalentTo(_testData) + .And.BeInAscendingOrder((item) => item.Key); + } + + [TestMethod] + public void ShouldBeEmptyWhenNotInitialized() + { + // Act + using var sortedList = new RecyclableSortedList(); + + // Validate + _ = sortedList.Should().BeEmpty(); + } + + [TestMethod] + public void ShouldBeSortedWhenInitialized() + { + // Act + using var sortedList = new RecyclableSortedList() + { + _testData[0], + _testData[1], + _testData[2], + _testData[3], + _testData[4] + }; + + // Validate + _ = sortedList.Should().NotBeEmpty() + .And.BeInAscendingOrder(x => x.Key) + .And.BeEquivalentTo(_testData); + } + + [TestMethod] + public void ShouldBeSortedWhenUpdateEnds() + { + // Prepare + using var sortedList = new RecyclableSortedList(); + + // Act + sortedList.BeginUpdate(); + foreach (var testItem in _testData) + { + sortedList.Add(testItem); + } + + // Validate + _ = sortedList.Should().BeInDescendingOrder(x => x.Key); + + // Act + sortedList.EndUpdate(); + + // Validate + _ = sortedList.Should().BeInAscendingOrder(x => x.Key); + } + + [TestMethod] + public void ShouldBeEmptyAfterClear() + { + // Prepare + using var sortedList = new RecyclableSortedList(_testData); + + // Act + sortedList.Clear(); + + // Validate + _ = sortedList.Should().BeEmpty(); + } + } +} \ No newline at end of file