Dictionary ,Hashtable and HashSet

HashTable

Represents a collection of key/value pairs that are organized based on the hash code of the key.

Hashtable optimizes lookups. It computes an adding hash of each key. It then uses this hash code to look up the element very quickly. It is an older .NET Framework type. It is slower than the generic Dictionary type.

Dictionary

A dictionary is used where fast lookups are critical. The Dictionary type provides fast lookups with keys to get values. With it we use keys and values of any type, including ints and strings. Dictionary requires a special syntax form.

Dictionary is used when we have many different elements. We specify its key type and its value type. It provides good performance.

Differences between Hashtable and Dictionary

Dictionary:

  • It returns error if we try to find a key which does not exist.
  • It is faster than a Hashtable because there is no boxing and unboxing.
  • Only public static members are thread safe.
  • Dictionary is a generic type which means we can use it with any data type.

Hashtable:

  • It returns null if we try to find a key which does not exist.
  • It is slower than dictionary because it requires boxing and unboxing.
  • All the members in a Hashtable are thread safe,
  • Hashtable is not a generic type,

Hashtable and Dictionary Collection Types

  • The System.Collections.Hashtable class, and the System.Collections.Generic.Dictionary<TKey, TValue> and System.Collections.Concurrent.ConcurrentDictionary<TKey, TValue> generic classes, implement the System.Collections.IDictionary interface. The Dictionary<TKey, TValue> generic class also implements the IDictionary<TKey, TValue> generic interface. Therefore, each element in these collections is a key-and-value pair.
  • A Hashtable object consists of buckets that contain the elements of the collection. A bucket is a virtual subgroup of elements within the Hashtable, which makes searching and retrieving easier and faster than in most collections. Each bucket is associated with a hash code, which is generated using a hash function and is based on the key of the element.
  • The generic HashSet<T> class is an unordered collection for containing unique elements. For more information about this collection, see HashSet Collection Type.
  • A hash function is an algorithm that returns a numeric hash code based on a key. The key is the value of some property of the object being stored. A hash function must always return the same hash code for the same key. It is possible for a hash function to generate the same hash code for two different keys, but a hash function that generates a unique hash code for each unique key results in better performance when retrieving elements from the hash table.
  • Each object that is used as an element in a Hashtable must be able to generate a hash code for itself by using an implementation of the GetHashCode method. However, you can also specify a hash function for all elements in a Hashtable by using a Hashtable constructor that accepts an IHashCodeProvider implementation as one of its parameters.
  • When an object is added to a Hashtable, it is stored in the bucket that is associated with the hash code that matches the object’s hash code. When a value is being searched for in the Hashtable, the hash code is generated for that value, and the bucket associated with that hash code is searched.
  • For example, a hash function for a string might take the ASCII codes of each character in the string and add them together to generate a hash code. The string “picnic” would have a hash code that is different from the hash code for the string “basket”; therefore, the strings “picnic” and “basket” would be in different buckets. In contrast, “stressed” and “desserts” would have the same hash code and would be in the same bucket.
  • The Dictionary<TKey, TValue> and ConcurrentDictionary<TKey, TValue>classes have the same functionality as the Hashtable class. A Dictionary<TKey, TValue> of a specific type (other than Object) provides better performance than a Hashtable for value types. This is because the elements of Hashtable are of type Object; therefore, boxing and unboxing typically occur when you store or retrieve a value type. The ConcurrentDictionary<TKey, TValue>class should be used when multiple threads might be accessing the collection simultaneously.

Dictionary

Hashtable

Each element is a key/value pair stored in a DictionaryEntry object. A key cannot be null, but a value can be.

The objects used as keys by a Hashtable are required to override the Object.GetHashCode method (or the IHashCodeProvider interface) and the Object.Equals method (or the IComparer interface). The implementation of both methods and interfaces must handle case sensitivity the same way; otherwise, the Hashtable might behave incorrectly. For example, when creating a Hashtable, we  must use the CaseInsensitiveHashCodeProvider class (or any case-insensitive IHashCodeProvider implementation) with the CaseInsensitiveComparer class (or any case-insensitive IComparer implementation).

Furthermore, these methods must produce the same results when called with the same parameters while the key exists in the Hashtable. An alternative is to use a Hashtable constructor with an IEqualityComparer parameter. If key equality were simply reference equality, the inherited implementation of Object.GetHashCode and Object.Equals would suffice.

Key objects must be immutable (unable to change ex–string) as long as they are used as keys in the Hashtable.

When an element is added to the Hashtable, the element is placed into a bucket based on the hash code of the key. Subsequent lookups of the key use the hash code of the key to search in only one particular bucket, thus substantially reducing the number of key comparisons required to find an element.

The load factor of a Hashtable determines the maximum ratio of elements to buckets. Smaller load factors cause faster average lookup times at the cost of increased memory consumption. The default load factor of 1.0 generally provides the best balance between speed and size. A different load factor can also be specified when the Hashtable is created.

As elements are added to a Hashtable, the actual load factor of the Hashtable increases. When the actual load factor reaches the specified load factor, the number of buckets in the Hashtable is automatically increased to the smallest prime number that is larger than twice the current number of Hashtable buckets.

Each key object in the Hashtable must provide its own hash function, which can be accessed by calling GetHash. However, any object implementing IHashCodeProvider can be passed to a Hashtable constructor, and that hash function is used for all objects in the table.

The capacity of a Hashtable is the number of elements the Hashtable can hold. As elements are added to a Hashtable, the capacity is automatically increased as required through reallocation.

For very large Hashtable objects, you can increase the maximum capacity to 2 billion elements on a 64-bit system by setting the enabled attribute of the gcAllowVeryLargeObjects configuration element to true in the run-time environment.

The foreach statement of the C# language (For Each in Visual Basic) requires the type of each element in the collection. Since each element of the Hashtable is a key/value pair, the element type is not the type of the key or the type of the value. Instead, the element type is DictionaryEntry. For example:

foreach(DictionaryEntry de in myHashtable)

{

// …

}

The foreach statement is a wrapper around the enumerator, which only allows reading from, not writing to, the collection.

Because serializing and deserializing an enumerator for a Hashtable can cause the elements to become reordered, it is not possible to continue enumeration without calling the Reset method.


Note
Because   keys can be inherited and their behavior changed, their absolute uniqueness   cannot be guaranteed by comparisons using the Equals method.

using System;
using System.Collections;

class Example
{
    public static void Main()
    {
        // Create a new hash table.
        //
        Hashtable openWith = new Hashtable();

        // Add some elements to the hash table. There are no
        // duplicate keys, but some of the values are duplicates.
        openWith.Add("txt", "notepad.exe");
        openWith.Add("bmp", "paint.exe");
        openWith.Add("dib", "paint.exe");
        openWith.Add("rtf", "wordpad.exe");

        // The Add method throws an exception if the new key is
        // already in the hash table.
        try
        {
            openWith.Add("txt", "winword.exe");
        }
        catch
        {
            Console.WriteLine("An element with Key = "txt" already exists.");
        }

        // The Item property is the default property, so you
        // can omit its name when accessing elements.
        Console.WriteLine("For key = "rtf", value = {0}.", openWith["rtf"]);

        // The default Item property can be used to change the value
        // associated with a key.
        openWith["rtf"] = "winword.exe";
        Console.WriteLine("For key = "rtf", value = {0}.", openWith["rtf"]);

        // If a key does not exist, setting the default Item property
        // for that key adds a new key/value pair.
        openWith["doc"] = "winword.exe";

        // ContainsKey can be used to test keys before inserting
        // them.
        if (!openWith.ContainsKey("ht"))
        {
            openWith.Add("ht", "hypertrm.exe");
            Console.WriteLine("Value added for key = "ht": {0}", openWith["ht"]);
        }

        // When you use foreach to enumerate hash table elements,
        // the elements are retrieved as KeyValuePair objects.
        Console.WriteLine();
        foreach( DictionaryEntry de in openWith )
        {
            Console.WriteLine("Key = {0}, Value = {1}", de.Key, de.Value);
        }

        // To get the values alone, use the Values property.
        ICollection valueColl = openWith.Values;

        // The elements of the ValueCollection are strongly typed
        // with the type that was specified for hash table values.
        Console.WriteLine();
        foreach( string s in valueColl )
        {
            Console.WriteLine("Value = {0}", s);
        }

        // To get the keys alone, use the Keys property.
        ICollection keyColl = openWith.Keys;

        // The elements of the KeyCollection are strongly typed
        // with the type that was specified for hash table keys.
        Console.WriteLine();
        foreach( string s in keyColl )
        {
            Console.WriteLine("Key = {0}", s);
        }

        // Use the Remove method to remove a key/value pair.
        Console.WriteLine("nRemove("doc")");
        openWith.Remove("doc");

        if (!openWith.ContainsKey("doc"))
        {
            Console.WriteLine("Key "doc" is not found.");
        }
    }
}

/* This code example produces the following output:

An element with Key = "txt" already exists.
For key = "rtf", value = wordpad.exe.
For key = "rtf", value = winword.exe.
Value added for key = "ht": hypertrm.exe

Key = dib, Value = paint.exe
Key = txt, Value = notepad.exe
Key = ht, Value = hypertrm.exe
Key = bmp, Value = paint.exe
Key = rtf, Value = winword.exe
Key = doc, Value = winword.exe

Value = paint.exe
Value = notepad.exe
Value = hypertrm.exe
Value = paint.exe
Value = winword.exe
Value = winword.exe

Key = dib
Key = txt
Key = ht
Key = bmp
Key = rtf
Key = doc

Remove("doc")
Key "doc" is not found.
 */

So here we go :

Hashtable Dictionary Hashset
Represents a collection of key/value pairs     that are organized based on the hash code of the key. Represents a collection of keys and     values. Dictionary<TKey, TValue> class is implemented as a hash     table.. HashSet class is an unordered collection     for containing unique elements.This class is based on the model of mathematical sets and     provides high-performance set operations
Each element is a key/value pair stored in     a DictionaryEntry object. Each element type is a KeyValuePair<TKey,     TValue> of the key type and the value type Each element type is the type of T defined     at the time of the creation of HashSet
Hashtable are of type Object; therefore,     boxing and unboxing typically occur when you store or retrieve a value type A Dictionary<TKey, TValue> of a     specific type (other than Object) provides better performance than a     Hashtable for value types A HashSet<T> collection is not     sorted and cannot contain duplicate elements.If order or element duplication is more important than     performance for your application, consider using the List<T> class     together with the Sort method.
Hashtable implements IDictionary<TKey,     TValue> Dictionary implements IDictionary<TKey,     TValue>, Starting with the .NET Framework version     4, the HashSet<T> class implements the ISet<T> class
Hashtable is thread safe for use by     multiple reader threads and a single writing thread. It is thread safe for     multi-thread use when only one of the threads perform write (update)     operations A Dictionary<TKey, TValue> can     support multiple readers concurrently, as long as the collection is not     modified. Any public static members of this type are     thread safe. Any instance members are not guaranteed to be thread safe.

Leave a Reply