Introduction
In this lesson, we will learn about Hashtables.
Which are one of the most useful collections in C#. We will see how to define them and how to use them and in which case scenarios we should take advantage of them.
To understand the concept of hashing and tables first think about a real dictionary
Assume we have a German/English Dictionary where every word in German corresponds to only one word in English. So when we try and translate the word ‘Auto’ in German, which translates to ‘Car’ in English, we used one word as a keyword to search, and we got the translation as a result.
This is exactly how hashtables and dictionaries in C# behave we use a key to get a value.
Another IT-related example is a student registration system where every student has an ID and many other data like name, age, grades, and picture. For such a system to work, we will need a special ID for every student. If we were to store this data using a hashtable or a dictionary, the student ID would be the Key, and the student data(Object containing all other student info).
would be the value
Section 1 Defining a Hashtable
While we are at it, let’s put our last example into action, and let’s implement a simple application that will create few objects of type ‘Student’ and store them into a hashtable using their IDs as keys and the object itself as a value.
First Let’s define our simple class with the following properties
- Id
- 2.Name
- 3.GPA
//simple class student
class Student{
//property called Id
public int Id { get; set; }
//property called Name
public string Name { get; set; }
//property called GPA
public float GPA { get; set; }
//simple constructor
public Student(int id,string name,float GPA) {
this.Id = id;
this.Name = name;
this.GPA = GPA;
}
}
we could create the class in a separate file as Student.cs but for simplicity let’s define it outside our Program Class
let’s define our hashtable and initialize it as we do with any other object in the main method.
using System;
using System.Collections;
namespace HashtableandDictionary {
class Program {
static void Main(string[] args) {
//defining an objet called table of type hashtable
Hashtable table = new Hashtable();
//pause
Console.ReadKey();
}
}
class Student{
public int Id { get; set; }
public string Name { get; set; }
public float GPA { get; set; }
public Student(int id,string name,float GPA) {
this.Id = id;
this.Name = name;
this.GPA = GPA;
}
}
}
Section 2 Adding Entries to our Hashtable
Great Now we can define and initialize few objects of our Student class
After we initialize them we will add them to our Hashtable we will use our student Id property as a key and the object it self as the value like we discussed earlier
For that we will use the object method from the Hashtable called Add(),
//creating few Students objects with different values
Student stud1 = new Student(1, "Maria", 98);
Student stud2 = new Student(2, "Json", 76);
Student stud3 = new Student(3, "Clara", 43);
Student stud4 = new Student(4, "Steve", 55);
//adding them to the table where the student Id is the key and the object it self is the value
table.Add(stud1.Id, stud1);
table.Add(stud2.Id, stud2);
table.Add(stud3.Id, stud3);
table.Add(stud4.Id, stud4);
Section 3 Fetching Entries from our Hashtable
Now let’s try fetching the data from our hashtable
We have a few options
The simplest one if we want to access an element that we already have its key is by accessing it using the hashtable object followed by [] just like an array
Since Hashtables are non-generic collections they will return an object which before we start working with we have to cast it back to type Student
//First we access the data from the collection by similar to an array like this table[stud1.Id]
//the we type cast it to type Student before we store it otherwise we will get an error telling us we can't sotre an Object inside a variable of type Student
Student storedStudent1 = (Student)table[stud1.Id];
//then we print the values of the student we fetched and stored in sotredStudent1
Console.WriteLine("Student ID:{0}, Name:{1}, GPA{2}", storedStudent1.Id, storedStudent1.Name, storedStudent1.GPA);
Let’s assume we want to actually print all the Data inside of our hashtable and we don’t have a particular Key at our disposal, we can simply do that by getting all the keys from our hashtable
To solve this first we have to discuss a struct called DictionaryEntry, whenever we add a new entry to our Hashtable (Key-value pair) a new DictionaryEntry object will be created for us and it will get inserted into our hashtable which means that a hashtable is basically a collection of DictionaryEntrys so using a temporary object of DictionaryEntry we can go through our hashtable using a for each loop
Now as we discussed our values in a non-generic collection will always be stored as of type Object so we have to typecast it to student first, and to avoid multiple typecasting many times inside a loop
we will do that once at the start of each iteration.
//dictionary entry holds the data of our key and value pair
foreach (DictionaryEntry entry in table) {
//a temp object to store our value
Student temp = (Student)entry.Value;
Console.WriteLine("Student ID:{0}",temp.Id);
Console.WriteLine("Student Name:{0}",temp.Name);
Console.WriteLine("Student GPA:{0}",temp.GPA);
}
Another less costly way would be to use a property of our hashtable called Values which will return a collection of values as it name implies and of course these values are of type object
//more optimized solution to get all values in a hashtable without getting the keys
//here we typecasted the values directly into student object
foreach (Student value in table.Values) {
Console.WriteLine("Student ID:{0}", value.Id);
Console.WriteLine("Student Name:{0}", value.Name);
Console.WriteLine("Student GPA:{0}", value.GPA);
}
Complete code.
using System;
using System.Collections;
namespace HashtableandDictionary {
class Program {
static void Main(string[] args) {
//defining an objet called table of type hashtable
Hashtable table = new Hashtable();
//creating few student objects
Student stud1 = new Student(1, "Maria", 98);
Student stud2 = new Student(2, "Jason", 76);
Student stud3 = new Student(3, "Clara", 43);
Student stud4 = new Student(4, "Steve", 55);
//adding the student objects to the table where the student Id is the key and the whole object is the value
table.Add(stud1.Id, stud1);
table.Add(stud2.Id, stud2);
table.Add(stud3.Id, stud3);
table.Add(stud4.Id, stud4);
//First we access the data from the collection by similar to an array like this table[stud1.Id]
//the we type cast it to type Student before we store it otherwise we will get an error telling us we can't sotre an Object inside a variable of type Student
Student storedStudent1 = (Student)table[stud1.Id];
//then we print the values of the student we fetched and stored in sotredStudent1
Console.WriteLine("Student ID:{0}, Name:{1}, GPA{2}", storedStudent1.Id, storedStudent1.Name, storedStudent1.GPA);
//dictionary entry holds the data of our key and value pair
foreach (DictionaryEntry entry in table) {
//a temp object to store our value
Student temp = (Student)entry.Value;
Console.WriteLine("Student ID:{0}",temp.Id);
Console.WriteLine("Student Name:{0}",temp.Name);
Console.WriteLine("Student GPA:{0}",temp.GPA);
}
//more optimized solution to get all values in a hashtable without getting the keys
//here we typecasted the values directly into student object
foreach (Student value in table.Values) {
Console.WriteLine("Student ID:{0}", value.Id);
Console.WriteLine("Student Name:{0}", value.Name);
Console.WriteLine("Student GPA:{0}", value.GPA);
}
//pause
Console.ReadKey();
}
}
class Student{
public int Id { get; set; }
public string Name { get; set; }
public float GPA { get; set; }
public Student(int id,string name,float GPA) {
this.Id = id;
this.Name = name;
this.GPA = GPA;
}
}
}
Challange
Consider the following array of students with this class definition
Student[] students = new Student[5];
students[0] = new Student(1, "Denis", 88);
students[1] = new Student(2, "Olaf", 97);
students[2] = new Student(6, "Ragner", 65);
students[3] = new Student(1, "Luise", 73);
students[4] = new Student(4, "Levi", 58);
Class Definition
class Student{
public int Id { get; set; }
public string Name { get; set; }
public float GPA { get; set; }
public Student(int id,string name,float GPA) {
this.Id = id;
this.Name = name;
this.GPA = GPA;
}
}
Write a program that will iterate through each element of the student’s array and insert them into a hashtable
If a student with the same ID already exists in the hashtable skip it and display the following error:
“Sorry, A student with the same ID already Exists”
Hint: Use the method ContainsKey() to check whether a student with the same ID already exist
Solution:
using System;
using System.Collections;
namespace HashtableandDictionary {
class Program {
static void Main(string[] args) {
//defining our table
Hashtable table = new Hashtable();
//our array of students
Student[] students = new Student[5];
students[0] = new Student(1, "Denis", 88);
students[1] = new Student(2, "Olaf", 97);
students[2] = new Student(6, "Ragner", 65);
students[3] = new Student(1, "Luise", 73);
students[4] = new Student(4, "Levi", 58);
//for each student in our students array
foreach (Student s in students) {
//first check if the student already exists, if our hashtable does not already contain our key (Student ID)
if (!table.ContainsKey(s.Id)) {
//if yes add the student to our hashtable and display a message
table.Add(s.Id, s);
Console.WriteLine("Student with ID{0} was added!.", s.Id);
} else {
//if no display an error message
Console.WriteLine("Sorry, A student with the same ID already exists ID:{0}",s.Id);
}
}
Console.ReadKey();
}
}
class Student{
public int Id { get; set; }
public string Name { get; set; }
public float GPA { get; set; }
public Student(int id,string name,float GPA) {
this.Id = id;
this.Name = name;
this.GPA = GPA;
}
}
}