diff --git a/collections-csharp/HashSetvsSortedSetInCSharp/HashSetvsSortedSetInCSharp/HashSetvsSortedSetInCSharp.csproj b/collections-csharp/HashSetvsSortedSetInCSharp/HashSetvsSortedSetInCSharp/HashSetvsSortedSetInCSharp.csproj index a6d8996d10..62be4f867f 100644 --- a/collections-csharp/HashSetvsSortedSetInCSharp/HashSetvsSortedSetInCSharp/HashSetvsSortedSetInCSharp.csproj +++ b/collections-csharp/HashSetvsSortedSetInCSharp/HashSetvsSortedSetInCSharp/HashSetvsSortedSetInCSharp.csproj @@ -2,13 +2,13 @@ Exe - net6.0 + net10.0 enable enable - + diff --git a/collections-csharp/HashSetvsSortedSetInCSharp/HashSetvsSortedSetInCSharp/Operations.cs b/collections-csharp/HashSetvsSortedSetInCSharp/HashSetvsSortedSetInCSharp/Operations.cs index 63b809592f..cadfb6b3eb 100644 --- a/collections-csharp/HashSetvsSortedSetInCSharp/HashSetvsSortedSetInCSharp/Operations.cs +++ b/collections-csharp/HashSetvsSortedSetInCSharp/HashSetvsSortedSetInCSharp/Operations.cs @@ -1,129 +1,135 @@ using BenchmarkDotNet.Attributes; using BenchmarkDotNet.Configs; -namespace HashSetvsSortedSetInCSharp +namespace HashSetvsSortedSetInCSharp; + +[MemoryDiagnoser] +[GroupBenchmarksBy(BenchmarkLogicalGroupRule.ByMethod)] +[Orderer(BenchmarkDotNet.Order.SummaryOrderPolicy.FastestToSlowest)] +[RankColumn] +public class Operations { - [MemoryDiagnoser] - [GroupBenchmarksBy(BenchmarkLogicalGroupRule.ByMethod)] - [Orderer(BenchmarkDotNet.Order.SummaryOrderPolicy.FastestToSlowest)] - [RankColumn] - public class Operations + private readonly List _numList; + private readonly HashSet _hashSet; + private readonly SortedSet _sortedSet; + private readonly int _searchValue; + private HashSet _hashSetCopy = []; + private SortedSet _sortedSetCopy = []; + + public Operations() + { + _numList = RandomInts(1000000); + _hashSet = InitializeIntHashSet(); + _sortedSet = InitializeIntSortedSet(); + _searchValue = int.MaxValue - 1; + } + + [Benchmark] + public HashSet InitializeIntHashSet() { - private readonly List _numList; - private readonly HashSet _hashSet; - private readonly SortedSet _sortedSet; - private readonly int _searchValue; + var hashSet = new HashSet(); - public Operations() + foreach (var number in _numList) { - _numList = RandomInts(1000000); - _hashSet = InitializeIntHashSet(); - _sortedSet = InitializeIntSortedSet(); - _searchValue = Int32.MaxValue - 1; + hashSet.Add(number); } - [Benchmark] - public HashSet InitializeIntHashSet() - { - var hashSet = new HashSet(); + return hashSet; + } - foreach (var number in _numList) - { - hashSet.Add(number); - } + [Benchmark] + public SortedSet InitializeIntSortedSet() + { + var sortedSet = new SortedSet(); - return hashSet; + foreach (var number in _numList) + { + sortedSet.Add(number); } - [Benchmark] - public SortedSet InitializeIntSortedSet() - { - var sortedSet = new SortedSet(); + return sortedSet; + } - foreach (var number in _numList) - { - sortedSet.Add(number); - } + [Benchmark] + public HashSet RemoveElementFromHashSet() + { + _hashSet.Remove(_searchValue); - return sortedSet; - } + return _hashSet; + } - [Benchmark] - public HashSet RemoveElementFromHashSet() - { - _hashSet.Remove(_searchValue); + [Benchmark] + public SortedSet RemoveElementFromSortedSet() + { + _sortedSet.Remove(_searchValue); - return _hashSet; - } + return _sortedSet; + } - [Benchmark] - public HashSet RemoveWhereFromHashSet() - { - _hashSet.RemoveWhere(IsOdd); + [IterationSetup(Targets = [nameof(RemoveWhereFromHashSet), nameof(RemoveWhereFromSortedSet)])] + public void CopySets() + { + _hashSetCopy = new HashSet(_hashSet); + _sortedSetCopy = new SortedSet(_sortedSet); + } - return _hashSet; - } + [Benchmark] + public HashSet RemoveWhereFromHashSet() + { + _hashSetCopy.RemoveWhere(IsOdd); - [Benchmark] - public SortedSet RemoveElementFromSortedSet() - { - _sortedSet.Remove(_searchValue); + return _hashSetCopy; + } - return _sortedSet; - } + [Benchmark] + public SortedSet RemoveWhereFromSortedSet() + { + _sortedSetCopy.RemoveWhere(IsOdd); - [Benchmark] - public SortedSet RemoveWhereFromSortedSet() - { - _sortedSet.RemoveWhere(IsOdd); + return _sortedSetCopy; + } - return _sortedSet; - } + [Benchmark] + public bool SearchSortedSet() + { + return _sortedSet.Contains(_searchValue); + } - [Benchmark] - public bool SearchSortedSet() - { - return _sortedSet.Contains(_searchValue); - } + [Benchmark] + public bool SearchHashSet() + { + return _hashSet.Contains(_searchValue); + } - [Benchmark] - public bool SearchHashSet() - { - return _hashSet.Contains(_searchValue); - } + [Benchmark] + public List SortHashSetElements() + { + return _hashSet.Order().ToList(); + } - [Benchmark] - public List SortHashSetElements() - { - var sortElements = _hashSet.OrderBy(element => element).ToList(); - - return sortElements; - } + [Benchmark] + public List SortSortedSetElements() + { + return _sortedSet.ToList(); + } - [Benchmark] - public List SortSortedSetElements() - { - return _sortedSet.ToList(); - } + private static List RandomInts(int size) + { + var rand = new Random(); + List numbers = []; - private List RandomInts(int size) + for (int i = 0; i < size - 1; i++) { - var rand = new Random(); - var numbers = new List(); - - for (int i = 0; i < size - 1; i++) - { - numbers.Add(rand.Next()); - } + numbers.Add(rand.Next()); + } - numbers.Add(Int32.MaxValue - 1); + numbers.Add(int.MaxValue - 1); - return numbers; - } + return numbers; + } - private bool IsOdd(int num) - { - return num % 2 == 1; - } + private static bool IsOdd(int num) + { + return num % 2 == 1; } } diff --git a/collections-csharp/HashSetvsSortedSetInCSharp/HashSetvsSortedSetInCSharp/Program.cs b/collections-csharp/HashSetvsSortedSetInCSharp/HashSetvsSortedSetInCSharp/Program.cs index 68378a5ef9..f3324bcf22 100644 --- a/collections-csharp/HashSetvsSortedSetInCSharp/HashSetvsSortedSetInCSharp/Program.cs +++ b/collections-csharp/HashSetvsSortedSetInCSharp/HashSetvsSortedSetInCSharp/Program.cs @@ -1,4 +1,4 @@ using BenchmarkDotNet.Running; using HashSetvsSortedSetInCSharp; -var summary = BenchmarkRunner.Run(); \ No newline at end of file +var summary = BenchmarkRunner.Run(args: args); diff --git a/collections-csharp/HashSetvsSortedSetInCSharp/HashSetvsSortedSetInCSharp/SetOrderExamples.cs b/collections-csharp/HashSetvsSortedSetInCSharp/HashSetvsSortedSetInCSharp/SetOrderExamples.cs new file mode 100644 index 0000000000..ec28e76ad8 --- /dev/null +++ b/collections-csharp/HashSetvsSortedSetInCSharp/HashSetvsSortedSetInCSharp/SetOrderExamples.cs @@ -0,0 +1,60 @@ +namespace HashSetvsSortedSetInCSharp; + +public record Book(string Title, int Year); + +public static class SetOrderExamples +{ + public static void PrintHashSetAndSortedSetOrder() + { + var hashSet = new HashSet { 1, 2, 3, 4, 5 }; + hashSet.Remove(2); + hashSet.Add(6); + + Console.WriteLine(string.Join(", ", hashSet)); + + var sortedSet = new SortedSet { 5, 1, 4, 2, 3 }; + sortedSet.Remove(2); + sortedSet.Add(6); + + Console.WriteLine(string.Join(", ", sortedSet)); + } + + public static OrderedDictionary TrackPagesInVisitOrder() + { + var visited = new OrderedDictionary(); + visited.TryAdd("home", true); + visited.TryAdd("pricing", true); + visited.TryAdd("home", true); + visited.TryAdd("docs", true); + + Console.WriteLine(string.Join(", ", visited.Keys)); + + return visited; + } + + public static SortedSet SortBooksByYear() + { + var byYear = Comparer.Create((a, b) => a.Year.CompareTo(b.Year)); + + var sortedBooks = new SortedSet(byYear) + { + new("Dune", 1965), + new("The Moon Is a Harsh Mistress", 1966), + new("Flowers for Algernon", 1966) + }; + + Console.WriteLine(sortedBooks.Count); + + return sortedBooks; + } + + public static HashSet BooksInHashSet() + { + return + [ + new("Dune", 1965), + new("The Moon Is a Harsh Mistress", 1966), + new("Flowers for Algernon", 1966) + ]; + } +} diff --git a/collections-csharp/HashSetvsSortedSetInCSharp/HashSetvsSortedSetInCSharpTests/HashSetvsSortedSetInCSharpTests.csproj b/collections-csharp/HashSetvsSortedSetInCSharp/HashSetvsSortedSetInCSharpTests/HashSetvsSortedSetInCSharpTests.csproj index 4a36ddb180..c77eef0e4c 100644 --- a/collections-csharp/HashSetvsSortedSetInCSharp/HashSetvsSortedSetInCSharpTests/HashSetvsSortedSetInCSharpTests.csproj +++ b/collections-csharp/HashSetvsSortedSetInCSharp/HashSetvsSortedSetInCSharpTests/HashSetvsSortedSetInCSharpTests.csproj @@ -1,7 +1,7 @@ - net6.0 + net10.0 enable enable @@ -9,10 +9,10 @@ - - - - + + + + diff --git a/collections-csharp/HashSetvsSortedSetInCSharp/HashSetvsSortedSetInCSharpTests/HashSetvsSortedSetUnitTests.cs b/collections-csharp/HashSetvsSortedSetInCSharp/HashSetvsSortedSetInCSharpTests/HashSetvsSortedSetUnitTests.cs index b4e653003d..831bf456f8 100644 --- a/collections-csharp/HashSetvsSortedSetInCSharp/HashSetvsSortedSetInCSharpTests/HashSetvsSortedSetUnitTests.cs +++ b/collections-csharp/HashSetvsSortedSetInCSharp/HashSetvsSortedSetInCSharpTests/HashSetvsSortedSetUnitTests.cs @@ -1,65 +1,64 @@ using HashSetvsSortedSetInCSharp; -namespace HashSetvsSortedSetInCSharpTests +namespace HashSetvsSortedSetInCSharpTests; + +[TestClass] +public class HashSetvsSortedSetUnitTests { - [TestClass] - public class HashSetvsSortedSetUnitTests - { - private readonly HashSet _hashSet; - private readonly SortedSet _sortedSet; - private readonly int _searchValue; - private readonly Operations _setObject; + private readonly HashSet _hashSet; + private readonly SortedSet _sortedSet; + private readonly int _searchValue; + private readonly Operations _setObject; - public HashSetvsSortedSetUnitTests() - { - _setObject = new Operations(); - _hashSet = _setObject.InitializeIntHashSet(); - _sortedSet = _setObject.InitializeIntSortedSet(); - _searchValue = Int32.MaxValue - 1; - } + public HashSetvsSortedSetUnitTests() + { + _setObject = new Operations(); + _hashSet = _setObject.InitializeIntHashSet(); + _sortedSet = _setObject.InitializeIntSortedSet(); + _searchValue = int.MaxValue - 1; + } - [TestMethod] - public void GivenASortedSet_WhenNotEmpty_VerifyCountAndContains() - { - Assert.IsInstanceOfType(_sortedSet, typeof(SortedSet)); - Assert.IsTrue(_sortedSet.Contains(_searchValue)); - } + [TestMethod] + public void GivenASortedSet_WhenNotEmpty_VerifyCountAndContains() + { + Assert.IsInstanceOfType(_sortedSet, typeof(SortedSet)); + Assert.IsTrue(_sortedSet.Contains(_searchValue)); + } - [TestMethod] - public void GivenAHashSet_WhenNotEmpty_VerifyCountAndContains() - { - Assert.IsInstanceOfType(_hashSet, typeof(HashSet)); - Assert.IsTrue(_hashSet.Contains(_searchValue)); - } + [TestMethod] + public void GivenAHashSet_WhenNotEmpty_VerifyCountAndContains() + { + Assert.IsInstanceOfType(_hashSet, typeof(HashSet)); + Assert.IsTrue(_hashSet.Contains(_searchValue)); + } - [TestMethod] - public void GivenASortedSet_WhenNotEmpty_VerifySuccessfullyEnumerated() - { - var numList = _setObject.SortSortedSetElements(); + [TestMethod] + public void GivenASortedSet_WhenNotEmpty_VerifySuccessfullyEnumerated() + { + var numList = _setObject.SortSortedSetElements(); - var firstNum = numList.First(); - var lastNum = numList.Last(); - var min = numList.Min(); - var max = numList.Max(); + var firstNum = numList.First(); + var lastNum = numList.Last(); + var min = numList.Min(); + var max = numList.Max(); - Assert.IsTrue(firstNum == min); - Assert.IsTrue(lastNum == max); - Assert.IsInstanceOfType(numList, typeof(List)); - } + Assert.IsTrue(firstNum == min); + Assert.IsTrue(lastNum == max); + Assert.IsInstanceOfType(numList, typeof(List)); + } - [TestMethod] - public void GivenAHashSet_WhenNotEmpty_VerifySuccessfullyEnumerated() - { - var numList = _setObject.SortHashSetElements(); + [TestMethod] + public void GivenAHashSet_WhenNotEmpty_VerifySuccessfullyEnumerated() + { + var numList = _setObject.SortHashSetElements(); - var firstNum = numList.First(); - var lastNum = numList.Last(); - var min = numList.Min(); - var max = numList.Max(); + var firstNum = numList.First(); + var lastNum = numList.Last(); + var min = numList.Min(); + var max = numList.Max(); - Assert.IsTrue(firstNum == min); - Assert.IsTrue(lastNum == max); - Assert.IsInstanceOfType(numList, typeof(List)); - } + Assert.IsTrue(firstNum == min); + Assert.IsTrue(lastNum == max); + Assert.IsInstanceOfType(numList, typeof(List)); } -} \ No newline at end of file +} diff --git a/collections-csharp/HashSetvsSortedSetInCSharp/HashSetvsSortedSetInCSharpTests/SetOrderExamplesUnitTests.cs b/collections-csharp/HashSetvsSortedSetInCSharp/HashSetvsSortedSetInCSharpTests/SetOrderExamplesUnitTests.cs new file mode 100644 index 0000000000..94aef4329f --- /dev/null +++ b/collections-csharp/HashSetvsSortedSetInCSharp/HashSetvsSortedSetInCSharpTests/SetOrderExamplesUnitTests.cs @@ -0,0 +1,71 @@ +using HashSetvsSortedSetInCSharp; + +namespace HashSetvsSortedSetInCSharpTests; + +[TestClass] +public class SetOrderExamplesUnitTests +{ + [TestMethod] + public void GivenASortedSet_WhenRemovingAndAdding_ThenElementsStayInAscendingOrder() + { + var lines = CaptureOutput(SetOrderExamples.PrintHashSetAndSortedSetOrder); + + Assert.AreEqual("1, 3, 4, 5, 6", lines[1]); + } + + [TestMethod] + public void GivenAHashSet_WhenRemovingAndAdding_ThenTheSameElementsComeBack() + { + var lines = CaptureOutput(SetOrderExamples.PrintHashSetAndSortedSetOrder); + var elements = lines[0].Split(", ").Select(int.Parse).ToList(); + + CollectionAssert.AreEquivalent(new List { 1, 3, 4, 5, 6 }, elements); + } + + [TestMethod] + public void GivenAnOrderedDictionary_WhenAddingDuplicateKeys_ThenKeysKeepInsertionOrder() + { + OrderedDictionary? visited = null; + var lines = CaptureOutput(() => visited = SetOrderExamples.TrackPagesInVisitOrder()); + + Assert.AreEqual("home, pricing, docs", lines[0]); + CollectionAssert.AreEqual(new List { "home", "pricing", "docs" }, visited!.Keys.ToList()); + } + + [TestMethod] + public void GivenASortedSetWithAYearComparer_WhenTwoBooksShareAYear_ThenTheSecondIsDropped() + { + SortedSet? books = null; + var lines = CaptureOutput(() => books = SetOrderExamples.SortBooksByYear()); + + Assert.AreEqual("2", lines[0]); + Assert.AreEqual(2, books!.Count); + Assert.IsFalse(books.Any(book => book.Title == "Flowers for Algernon")); + } + + [TestMethod] + public void GivenAHashSet_WhenTwoBooksShareAYear_ThenBothAreKept() + { + var books = SetOrderExamples.BooksInHashSet(); + + Assert.AreEqual(3, books.Count); + } + + private static string[] CaptureOutput(Action action) + { + var originalOut = Console.Out; + using var writer = new StringWriter(); + Console.SetOut(writer); + + try + { + action(); + } + finally + { + Console.SetOut(originalOut); + } + + return writer.ToString().Split(Environment.NewLine, StringSplitOptions.RemoveEmptyEntries); + } +}