/// <summary> /// Initializes hashtable with given equality comparer of T and capacity equal to smallest prime number bigger than provided value. /// </summary> public HashTable(int capacity, EqualityComparer <T> equalityComparer) { if (equalityComparer == null) { throw new ArgumentNullException("Comparer is null"); } this.equalityComparer = equalityComparer; if (capacity < 0) { throw new ArgumentException("Capacity can't be negative"); } // set buckets capacity to next smallest prime if (capacity < 17) { capacity = 17; } else { ulong cap = NumericAlgorithms.FindNextPrime((ulong)capacity); capacity = cap > int.MaxValue ? int.MaxValue : (int)cap; //int.MaxValue is prime } bucketsCapacity = capacity; buckets = new LinkedList <T> [bucketsCapacity]; }
/// <summary> /// Initializes hashtable with given equality comparer and capacity equal to smallest prime number bigger than collection.count /// </summary> public HashTable(IEnumerable <T> collection, EqualityComparer <T> equalityComparer) { if (equalityComparer == null) { throw new ArgumentNullException("Comparer is null"); } this.equalityComparer = equalityComparer; // set buckets capacity to next smallest prime if (collection == null) { throw new ArgumentNullException("Collection is null"); } if (collection is IList <T> ) { bucketsCapacity = (collection as IList <T>).Count; } else { int cap = 0; foreach (var item in collection) { cap++; } bucketsCapacity = cap; } if (bucketsCapacity < 17) { bucketsCapacity = 17; } else { ulong cap = NumericAlgorithms.FindNextPrime((ulong)bucketsCapacity); bucketsCapacity = cap > int.MaxValue ? int.MaxValue : (int)cap; //int.MaxValue is prime } buckets = new LinkedList <T> [bucketsCapacity]; // add collection elements to hashtable foreach (var item in collection) { this.Add(item); } }
/// <summary> /// Adds new item to hashtable. Might cause a reallocation. /// </summary> public void Add(T item) { int hashCode = equalityComparer.GetHashCode(item); int bucketIndex = hashCode % bucketsCapacity; if (buckets[bucketIndex] == null) { buckets[bucketIndex] = new LinkedList <T>(); bucketsCount++; } buckets[bucketIndex].Add(item); elementsCount++; //-------------------------- reallocate the buckets collection if required // get new bucket capacity if required if (LoadFactor <= MaxLoadFactor) { return; } ulong newBucketsCapacity = 17; if (bucketsCapacity < int.MaxValue / 2) { newBucketsCapacity = (ulong)bucketsCapacity * 2; newBucketsCapacity = NumericAlgorithms.FindNextPrime((ulong)newBucketsCapacity); } else { newBucketsCapacity = int.MaxValue; //its prime } // for each value in hash table get new index in new reallocated array, copy that value and count new buckets var newBuckets = new LinkedList <T> [newBucketsCapacity]; int newBucketsCount = 0; for (int i = 0; i < buckets.Length; i++) { if (buckets[i] != null) { var list = buckets[i]; if (list.Count != 0) { foreach (T value in list) { hashCode = equalityComparer.GetHashCode(value); int newBucketIndex = hashCode % (int)newBucketsCapacity; if (newBuckets[newBucketIndex] == null) { newBuckets[newBucketIndex] = new LinkedList <T>(); newBucketsCount++; } newBuckets[newBucketIndex].Add(value); } } } } // copy new values buckets = newBuckets; bucketsCapacity = (int)newBucketsCapacity; bucketsCount = newBucketsCount; }