/// <summary> /// set the comparer to use when getting the hash code. /// If comparer is null, the current comparer is not changed. /// </summary> public static void SetComparer <TKey>(SimpleSet <TKey> Set, IEqualityComparer <TKey> comparer) { if (comparer != null) { Set.Comparer = comparer; } }
/// <summary> /// Adds the value to the set using the key. /// If replace is true and the key is already present on the set, we will replace the value, /// if false, we will return false to signal the failure. /// </summary> public static void Add <TKey>(SimpleSet <TKey> Set, TKey key) { var hash = Set.Comparer.GetHashCode(key); var index = (hash & int.MaxValue) % Set.Capacity; var inserted = false; var entry = Set.Entries[index]; if (entry != null) { // If we find a entry with the given key, validate if it's the same key // this is needed because two keys can produce the same hash if (entry.HashCode != hash && !Set.Comparer.Equals(key, entry.Key)) { // It's a collision, create an entry and add to the linked list of collisions var newEntry = CreateEntry(Set, key, hash); // Find the last element of the collision chain while (entry.Next != null) { entry = entry.Next; } entry.Next = newEntry; inserted = true; if (Set.Count >= Set.Capacity) { Expand(Set); } } } // Did not found, create and add an entry else { var newEntry = CreateEntry(Set, key, hash); if (Set.Count >= Set.Capacity) { Expand(Set); } Set.Entries[index] = newEntry; inserted = true; } if (inserted) { Set.Count++; } }
/// <summary> /// Creates a new set entry with the given values. /// </summary> private static SetEntry <TKey> CreateEntry <TKey>(SimpleSet <TKey> Set, TKey key, int hash) { SetEntry <TKey> newEntry; if (Set.EntryPool.Count > 0) { newEntry = Set.EntryPool[Set.EntryPool.Count - 1]; SList.RemoveLast(Set.EntryPool); // remove last for better perfomance } else { newEntry = new SetEntry <TKey>(); } newEntry.Key = key; newEntry.HashCode = hash; return(newEntry); }
/// <summary> /// Creates a fake hash set with the given capacity. /// This will also create an pool of SetEntry (the internal class used to store elements /// on the array) to reduce garbage generation and improve performance. /// If preWarmPool is true, this will pre-instantiate the elements on the pool. /// If preWarmPool is false, this will only create a SimpleSet of size 'size' and /// pool removed elements from the set for later reuse. /// </summary> public static SimpleSet <TKey> Create <TKey>(int size, bool preWarmPool) { var Set = new SimpleSet <TKey>(); Set.Count = 0; Set.Capacity = GetNextLength(size); Set.Entries = new SetEntry <TKey> [Set.Capacity]; Set.Comparer = EqualityComparer <TKey> .Default; Set.Enumerator = new SimpleSetEnumerator <TKey>(); Set.Enumerator.Set = Set; Set.EntryPool = SList.Create <SetEntry <TKey> >(size); if (preWarmPool) { for (int i = 0; i < size; i++) { Set.EntryPool[i] = new SetEntry <TKey>(); } } return(Set); }