Evaluate these classes.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Sockets;
using System.Text;
using System.Threading.Tasks;

namespace Assignment_4
{
    public class HashMap<K, V> : IMap<K, V>
    {
        /* Properties */

        public Entry<K, V>[] Table { get; set; }
        public int Capacity { get; set; }
        public double LoadFactor { get; set; }
        public int size; // Had to use a field to satisfy the IMap requirements of using the Size() method.
        public int Placeholders { get; set; } // Keeps track of the number of placeholders in the HashMap.

        /* Constructors */

        public HashMap()
        {
            this.Capacity = 11;
            this.Table = new Entry<K, V>[this.Capacity];
            this.LoadFactor = 0.75;
            this.size = 0;
        }

        public HashMap(int initialCapacity)
        {
            if (initialCapacity <= 0)
            {
                throw new ArgumentException();
            }

            this.Capacity = initialCapacity;
            this.Table = new Entry<K, V>[this.Capacity];
            this.LoadFactor = 0.75;
            this.size = 0;
        }

        public HashMap(int initialCapacity, double loadFactor)
        {
            if (initialCapacity <= 0 || loadFactor <= 0)
            {
                throw new ArgumentException();
            }

            this.Capacity = initialCapacity;
            this.Table = new Entry<K, V>[this.Capacity];
            this.LoadFactor = loadFactor;
            this.size = 0;
        }

        /* Methods */

        /// <summary>
        /// Returns the current size.
        /// </summary>
        /// <returns></returns>
        public int Size()
        {
            return this.size;
        }

        /// <summary>
        /// Returns true if number of ctive entries in the array is 0.
        /// </summary>
        /// <returns></returns>
        public bool IsEmpty()
        {
            return this.size == 0;
        }

        /// <summary>
        /// Wipes out the array and all placeholders.
        /// </summary>
        public void Clear()
        {
            Array.Clear(this.Table, 0, this.Table.Length);
            this.size = 0;
            this.Placeholders = 0;
        }

        /// <summary>
        /// Looks for the next available bucket based on the key passed.
        /// </summary>
        /// <param name="key"></param>
        /// <returns></returns>
        /// <exception cref="InvalidOperationException"></exception>
        public int GetMatchingOrNextAvailableBucket(K key)
        {
            int startPosition = Math.Abs(key.GetHashCode()) % this.Table.Length;

            for (int i = 0; i < this.Capacity; i++)
            {
                int bucket = (startPosition + i) % this.Capacity;

                if (this.Table[bucket] == null || this.Table[bucket].Key.Equals(key))
                {
                    return bucket;
                }
            }

            throw new InvalidOperationException("“No available bucket found.");
        }

        /// <summary>
        /// Returns the value located at the bucket found by hashing the key.
        /// </summary>
        /// <param name="key"></param>
        /// <returns></returns>
        /// <exception cref="ArgumentNullException"></exception>
        public V Get(K key)
        {
            if (key == null)
            {
                throw new ArgumentNullException();
            }

            int bucket = GetMatchingOrNextAvailableBucket(key);

            if (this.Table[bucket] != null && this.Table[bucket].Key.Equals(key))
            {
                return this.Table[bucket].Value;
            }
            else
            {
                return default(V); // If no matching key is found, return the default value of the V type.
            }
        }

        /// <summary>
        /// Adds or updates the bucket found by hashing the key. If the bucket is emtpy insert a new entry with the passed key and value pair and return default.
        /// </summary>
        /// <param name="key"></param>
        /// <param name="value"></param>
        /// <returns></returns>
        /// <exception cref="ArgumentNullException"></exception>
        public V Put(K key, V value)
        {
            if (key == null)
            {
                throw new ArgumentNullException();
            }
            if (value == null)
            {
                throw new ArgumentNullException();
            }

            if ((this.size + this.Placeholders + 1) >= (int)(this.Capacity * this.LoadFactor))
            {
                ReHash();
            }

            int bucket = GetMatchingOrNextAvailableBucket(key);

            for (Entry<K, V> entry = this.Table[bucket]; entry != null; entry = entry.Next)
            {
                if (entry.Key.Equals(key))
                {
                    V oldValue = entry.Value;
                    entry.Value = value;

                    return oldValue;
                }
            }

            Entry<K, V> newEntry = new Entry<K, V>(key, value);
            newEntry.Next = this.Table[bucket];
            this.Table[bucket] = newEntry;
            this.size++;

            return default(V);
        }

        /// <summary>
        /// Looks u the buket based on the hashcode of the key. If a value exists at this bucket, set the value to null and icnrease plaecholder counter by one.
        /// </summary>
        /// <param name="key"></param>
        /// <returns></returns>
        /// <exception cref="ArgumentNullException"></exception>
        public V Remove(K key)
        {
            if (key == null)
            {
                throw new ArgumentNullException();
            }

            int bucket = GetMatchingOrNextAvailableBucket(key);

            if (this.Table[bucket] != null && this.Table[bucket].Key.Equals(key))
            {
                V removedValue = this.Table[bucket].Value;
                this.Table[bucket].Value = default(V);
                this.Placeholders++;
                this.size--;

                return removedValue;
            }
            else
            {
                return default(V); // If no matching key is found, return the default value of the V type.
            }
        }

        /// <summary>
        /// During a rehash, a new array size must be calculated. We start by doubling the original size, adding 1 and finding the next prime number.
        /// </summary>
        /// <returns></returns>
        private int ReSize()
        {
            int newCapacity = this.Capacity;

            // Find the nearest prime number greater than or equal to double the current capacity.
            if (newCapacity == 1)
            {
                newCapacity = 2;
            }
            else
            {
                newCapacity = this.Capacity * 2;

                while (!IsPrime(newCapacity))
                {
                    newCapacity++;
                }
            }

            return newCapacity;
        }

        /// <summary>
        /// Occurs when the threshold (table length * load factor) is reached when adding a new Entry<K,V> to the Table.
        /// </summary>
        public void ReHash()
        {
            Entry<K, V>[] oldTable = this.Table;
            int newCapacity = ReSize(); // Store the result of ReSize() in a local variable
            Entry<K, V>[] newTable = new Entry<K, V>[newCapacity]; // Create a new table with the updated Capacity

            this.size = 0; // Reset the size to 0 as we’ll be adding back all the elements.
            this.Placeholders = 0;

            // Rehash the entire hash map by iterating through the oldTable.
            for (int i = 0; i < oldTable.Length; i++)
            {
                Entry<K, V> entry = oldTable[i];
                while (entry != null)
                {
                    Entry<K, V> nextEntry = entry.Next;
                    int startPosition = Math.Abs(entry.Key.GetHashCode()) % newTable.Length;

                    for (int j = 0; j < newCapacity; j++)
                    {
                        int bucket = (startPosition + j) % newCapacity;

                        if (newTable[bucket] == null)
                        {
                            newTable[bucket] = entry;
                            entry.Next = null;
                            this.size++;
                            break;
                        }
                    }

                    entry = nextEntry;
                }
            }

            this.Table = newTable;
            this.Capacity = newCapacity;
        }

        /// <summary>
        /// Returns an IEnumerator compatible object containing only the values of each Entry in the Table.
        /// </summary>
        /// <returns></returns>
        public IEnumerator<V> Values()
        {
            List<V> valuesList = new List<V>();

            for (int i = 0; i < this.Capacity; i++)
            {
                Entry<K, V> entry = this.Table[i];

                if (entry != null && entry.Value != null)
                {
                    valuesList.Add(entry.Value);
                }
            }
            return valuesList.GetEnumerator();
        }

        /// <summary>
        /// Returns an IEnumerator compatible object containing only the keys of each Entry in the Table.
        /// </summary>
        /// <returns></returns>
        public IEnumerator<K> Keys()
        {
            List<K> keysList = new List<K>();

            for (int i = 0; i < this.Capacity; i++)
            {
                Entry<K, V> entry = this.Table[i];

                if (entry != null && entry.Value != null)
                {
                    keysList.Add(entry.Key);
                }
            }

            return keysList.GetEnumerator();
        }

        /// <summary>
        /// Checks to see if the number passed is a prime number or not.
        /// </summary>
        /// <param name="number"></param>
        /// <returns></returns>
        private bool IsPrime(int number)
        {
            if (number <= 1) return false;

            if (number == 2 || number == 3) return true;

            if (number % 2 == 0) return false;

            for (int i = 3; i * i <= number; i += 2)
            {
                if (number % i == 0) return false;
            }

            return true;
        }
    }
}


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Assignment_4
{
    public class Entry<K, V>
    {
        /* Properties */

        public K Key { get; set; }
        public V Value { get; set; }
        public Entry<K, V> Next { get; set; } // Used for the next entry in HashMap.cs

        /* Constructors */

        public Entry(K key, V value)
        {
            this.Key = key;
            this.Value = value;
        }
    }
}