Hashtable trong C#

Ở trong hướng dẫn trước chúng ta đã tìm hiểu về lớp SortedList trong C# - một non-generic collection trong loạt bài hướng dẫn về Collection trong C#.  SortedList lưu trữ và sắp xếp các phần tử kiểu khóa-giá trị. Bạn có thể tìm hiểu SortedList tại đây nếu như chưa xem:

SortedList trong C# | Comdy
SortedList trong C# là gì? SortedList trong C# dùng để làm gì? Cách sử dụng SortedList trong C#.

Trong hướng dẫn này chúng ta sẽ tìm hiểu về lớp Hashtable trong C#. Hashtable cũng tương tự như SortedList - là một non-generic collection thuộc namespace System.Collections. Nó cũng lưu trữ các cặp khóa - giá trị như SortedList.

Tuy nhiên Hashtable khác SortedList ở chỗ nó tạo mã băm của từng khóa và lưu trữ nó trong một nhóm nội bộ.

Nếu bạn chưa biết generic collection và non-generic collection trong C# là gì thì có thể tham khảo ở bài viết này:

Collection trong C# | Comdy
Collection trong C# là gì? Có những loại collection nào trong C#. Tác dụng và cách sử dụng của từng loại collection.

Sơ đồ sau minh họa hệ thống phân cấp lớp Hashtable.

Hastable trong C#

Các thành viên quan trọng của Hashtable

Các phương thức quan trọng trong Hashtable:

Thuộc tính Miêu tả
Count Trả về tổng số cặp khóa / giá trị trong Hashtable.
IsReadOnly Trả về giá trị boolean cho biết liệu Hashtable có ở chế độ chỉ đọc hay không.
Item Trả về hoặc thiết lập giá trị được liên kết với khóa được chỉ định.
Keys Trả về được một ICollection của các khóa trong Hashtable.
Values Trả về được một ICollection của các giá trị trong Hashtable.
Phương thức Miêu tả
Add Thêm một phần tử với khóa và giá trị vào Hashtable.
Remove Xóa phần tử với khóa được chỉ định khỏi Hashtable.
Clear Loại bỏ tất cả các phần tử từ Hashtable.
Contains Kiểm tra xem Hashtable có chứa một khóa cụ thể không.
ContainsKey Kiểm tra xem Hashtable có chứa một khóa cụ thể không.
ContainsValue Kiểm tra xem Hashtable có chứa một giá trị cụ thể không.
GetHash Trả về mã băm cho khóa được chỉ định.

Thêm khóa-giá trị vào Hashtable

Phương thức Add() thêm một phần tử có khóa và giá trị vào Hashtable. Khóa và giá trị có thể thuộc bất kỳ loại dữ liệu nào. Khóa không thể là null trong khi giá trị có thể là null.

Ví dụ sau minh họa thêm khóa và giá trị vào Hashtable:

Hashtable ht = new Hashtable();

ht.Add(1, "One");
ht.Add(2, "Two");
ht.Add(3, "Three");
ht.Add(4, "Four");
ht.Add(5, null);
ht.Add("Fv", "Five");
ht.Add(8.5F, 8.5);

Bạn cũng có thể gán khóa và giá trị tại thời điểm khởi tạo bằng cú pháp khởi tạo đối tượng như sau:

Hashtable ht = new Hashtable()
{
	{ 1, "One" },
	{ 2, "Two" },
	{ 3, "Three" },
	{ 4, "Four" },
	{ 5, null },
	{ "Fv", "Five" },
	{ 8.5F, 8.5 }
};

Hashtable có thể bao gồm tất cả các phần tử của Dictionary như ví dụ dưới đây:

Dictionary<int, string> dict = new Dictionary<int, string>();

dict.Add(1, "one");
dict.Add(2, "two");
dict.Add(3, "three");

Hashtable ht = new Hashtable(dict);
Lưu ý: phương thức Add() sẽ đưa ra một ngoại lệ nếu bạn cố gắng thêm một khóa đã tồn tại trong Hashtable. Vì vậy, luôn luôn kiểm tra khóa bằng phương thức Contains() hoặc ContainsKey() trước khi thêm cặp khóa-giá trị vào Hashtable.

Truy cập Hashtable

Bạn có thể lấy lại giá trị của một khóa hiện có từ Hashtable bằng cách sử dụng bộ chỉ mục. Xin lưu ý rằng bộ chỉ mục Hashtable yêu cầu khóa.

Ví dụ dưới đây minh họa truy cập giá trị của Hashtable:

Hashtable ht = new Hashtable();

ht.Add(1, "One");
ht.Add(2, "Two");
ht.Add(3, "Three");
ht.Add(4, "Four");
ht.Add("Fv", "Five");
ht.Add(8.5F, 8.5F);
    
string strValue1 = (string)ht[2];
string strValue2 = (string)ht["Fv"];
float fValue = (float) ht[8.5F];

Console.WriteLine(strValue1);
Console.WriteLine(strValue2);
Console.WriteLine(fValue);

Đây là kết quả khi biên dịch và chạy chương trình:

Two
Five
8.5
Lưu ý: Hashtable là một non-generic collection vì vậy nó có thể chứa khóa và giá trị của bất kỳ loại dữ liệu nào. Vì vậy, các giá trị phải được ép kiểu dữ liệu thích hợp nếu không nó sẽ gây ra lỗi khi biên dịch.

Các phần tử băm là các cặp khóa-giá trị được lưu trữ trong DictionaryEntry. Vì vậy, bạn ép kiểu từng phần tử trong Hashtable sang DictionaryEntry. Sử dụng câu lệnh foreach để duyệt Hashtable, như ví dụ dưới đây:

Hashtable hashtable = new Hashtable()
{
	{ 1, "One" },
	{ 2, "Two" },
	{ 3, "Three" },
	{ 4, "Four" },
	{ 5, null },
	{ "Fv", "Five" },
	{ 8.5F, 8.5 }
};

foreach (DictionaryEntry item in hashtable)
{
	Console.WriteLine("key:{0}, value:{1}",item.Key, item.Value);
}

Đây là kết quả khi biên dịch và chạy chương trình:

Key: Fv, Value: Five
Key: 8.5, Value: 8.5
Key: 5, Value:
Key: 4, Value: Four
Key: 3, Value: Three
Key: 2, Value: Two
Key: 1, Value: One

Hashtable có thuộc tính KeysValues chứa tất cả các khóa và giá trị tương ứng. Bạn có thể sử dụng các thuộc tính này để lấy các khóa và giá trị.

Hashashtableable hashashtableable = new Hashashtableable();
{
	{ 1, "One" },
	{ 2, "Two" },
	{ 3, "Three" },
	{ 4, "Four" },
	{ 5, null },
	{ "Fv", "Five" },
	{ 8.5F, 8.5 }
};

foreach (var key in hashtable.Keys)
{
	Console.WriteLine("Key:{0}, Value:{1}", key, hashtable[key]);
}

Console.WriteLine("***All Values***");
        
foreach (var value in hashtable.Values)
{
	Console.WriteLine("Value:{0}", value);
}

Đây là kết quả khi biên dịch và chạy chương trình:

Key:Fv, Value:Five
Key:8.5, Value:8.5
Key:5, Value:
Key:4, Value:Four
Key:3, Value:Three
Key:2, Value:Two
Key:1, Value:One
***All Values***
Value:Five
Value:8.5
Value:
Value:Four
Value:Three
Value:Two
Value:One

Xóa các phần tử trong Hashtable

Phương thức Remove() xóa phần tử bằng khóa được chỉ định khỏi Hashtable.

Ví dụ sau sẽ minh họa xóa phần tử trong Hashtable:

Hashtable hashtable = new Hashtable()
{
	{ 1, "One" },
	{ 2, "Two" },
	{ 3, "Three" },
	{ 4, "Four" },
	{ "Fv", "Five" },
	{ 8.5F, 8.5 }
};

hashtable.Remove("Fv");

foreach (var key in hashtable.Keys)
{
	Console.WriteLine("Key:{0}, Value:{1}", key, hashtable[key]);
}

Đây là kết quả khi biên dịch và chạy chương trình:

Key:8.5, Value:8.5
Key:4, Value:Four
Key:3, Value:Three
Key:2, Value:Two
Key:1, Value:One

Kiểm tra phần tử tồn tại trong Hashtable

Các phương thức Contains()ContainsKey() kiểm tra xem khóa đã chỉ định có tồn tại trong Hashtable hay không.

Phương thức ContainsValue() kiểm tra xem giá trị được chỉ định có tồn tại trong Hashtable hay không.

Ví dụ dưới đây minh họa kiểm tra tồn tại khóa và giá trị trong Hashtable:

Hashashtableable hashtable = new Hashashtableable()
{
	{ 1, "One" },
	{ 2, "Two" },
	{ 3, "Three" },
	{ 4, "Four" }
};

Console.WriteLine(hashtable.Contains(2));// returns true
Console.WriteLine(hashtable.ContainsKey(2));// returns true
Console.WriteLine(hashtable.Contains(5)); //returns false
Console.WriteLine(hashtable.ContainsValue("One")); // returns true		

Đây là kết quả khi biên dịch và chạy chương trình:

True
True
False
True

Xóa tất cả phần tử trong Hashtable

Phương thức Clear() loại bỏ tất cả các cặp khóa-giá trị trong Hashtable. Ví dụ dưới đây minh họa điều này:

Hashashtableable hashtable = new Hashashtableable()
{
	{ 1, "One" },
	{ 2, "Two" },
	{ 3, "Three" },
	{ 4, "Four" },
	{ 5, null },
	{ "Fv", "Five" },
	{ 8.5F, 8.5 }
};

hashtable.Clear(); // removes all elements
Console.WriteLine("Total Elements: {0}", hashtable.Count);

Đây là kết quả khi biên dịch và chạy chương trình:

Total Elements: 0

Sự khác biệt giữa Hashtable và Dictionary

Bảng sau liệt kê sự khác biệt giữa Hashtable và Dictionary trong C#.

Hashtable Dictionary
Hashtable là non-generic collection thuộc namespace System.Collections. Dictionary là generic collection thuộc namespace System.Collections.Generic.
Hashtable là một non-generic collection, điều này có nghĩa là nó lưu trữ các cặp khóa-giá trị của bất kỳ kiểu dữ liệu nào. Dictionary là một generic collection. Vì vậy, nó có thể lưu trữ các cặp khóa-giá trị của các kiểu dữ liệu cụ thể.
Hashtable là thread safe. Chỉ các thành viên public static của Dictionary là thread safe.
Hashtable trả về null nếu chúng ta cố gắng tìm một khóa không tồn tại. Dictionary ném một ngoại lệ nếu chúng ta cố gắng tìm một khóa không tồn tại.
Truy xuất dữ liệu chậm hơn Dictionary vì phải unboxing. Truy xuất dữ liệu nhanh hơn Hashtable vì định kiểu mạnh.

Những điểm cần nhớ:

  • Hashtable lưu trữ các cặp khóa-giá trị của bất kỳ kiểu dữ liệu nào trong đó khóa phải là duy nhất.
  • Khóa Hashtable không thể null trong khi giá trị có thể là null.
  • Hashtable lấy một phần tử bằng cách so sánh mã băm của các khóa. Vì vậy, nó có hiệu suất chậm hơn so với Dictionary.
  • Hashtable sử dụng trình băm mặc định là Object.GetHashCode(). Bạn cũng có thể sử dụng một trình băm tùy chỉnh.
  • Sử dụng DictionaryEntry với câu lệnh foreach để duyệt Hashtable.

Ở hướng dẫn tiếp theo, chúng ta sẽ tìm hiểu về Stack trong C#. Stack là một collection đặc biệt lưu trữ các phần tử dạng LIFO (Last In First Out - vào sau ra trước).

Stack trong C# | Comdy
Stack trong C# là gì? Stack trong C# dùng để làm gì? Cách sử dụng Stack trong C#.
Lập Trình C#Lập Trình C# Cơ Bản
Bài Viết Liên Quan:
int[] và int[,] trong C#: Ai nhanh hơn
Trung Nguyen 10/10/2020
int[] và int[,] trong C#: Ai nhanh hơn

Hiểu được sự khác biệt giữa các loại mảng trong C# sẽ giúp bạn chọn cấu trúc dữ liệu chính xác cho mọi trường hợp.

Struct và class trong C#: Ai nhanh hơn
Trung Nguyen 09/10/2020
Struct và class trong C#: Ai nhanh hơn

Trong bài viết này, tôi sẽ so sánh sự khác biệt về hiệu suất giữa struct và class trong C#: Ai nhanh hơn.

Best practice cho performance trong C#
Trung Nguyen 03/10/2020
Best practice cho performance trong C#

Mục tiêu của bài viết này là cung cấp một danh sách không đầy đủ các code mẫu cần tránh, vì chúng rủi ro hoặc performance kém.

Đọc ghi file (File I/O) trong C#
Trung Nguyen 26/04/2020
Đọc ghi file (File I/O) trong C#

Hướng dẫn này sẽ giúp bạn tìm hiểu về đọc ghi file (File I/O) trong C# và sử dụng các lớp tiện ích để đọc ghi file.