SortedList trong C#

Ở trong hướng dẫn trước chúng ta đã tìm hiểu về lớp ArrayList trong C# - một non-generic collection trong loạt bài hướng dẫn về Collection trong C#. ArrayList được sử dụng để lưu trữ các phần tử của bất kỳ kiểu dữ liệu nào. Nó tương tự như một mảng nhưng không cần phải chỉ định kích thước khi khởi tạo và nó có khả năng tự thay đổi kích thước. Bạn có thể tìm hiểu ArrayList tại đây nếu như chưa xem:

ArrayList trong C# | Comdy
ArrayList trong C# là gì? Cách sử dụng các phương thức phổ biến của ArrayList trong C#.

SortedList lưu trữ các cặp khóa và giá trị theo thứ tự tăng dần của khóa theo mặc định. Lớp SortedList triển khai thực hiện các interface IDictionary và ICollection, do đó các phần tử có thể được truy cập bằng cả khóa và chỉ mục.

C# bao gồm hai loại SortedList là generic và non-generic. Ở đây, chúng ta sẽ tìm hiểu về SortedList non-generic.

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 SortedList non-generic.

SortedList trong C#

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

Các thuộc tính quan trọng của SortedList:

Thuộc tính Miêu tả
Capacity Trả về hoặc thiết lập số lượng phần tử mà đối tượng SortedList có thể lưu trữ.
Count Trả về số lượng phần tử thực sự có trong SortedList.
IsFixedSize Trả về một giá trị cho biết liệu SortedList có kích thước cố định hay không.
IsReadOnly Trả về một giá trị cho biết liệu SortedList là chỉ đọc hay không.
Item Trả về hoặc thiết lập phần tử tại khóa được chỉ định trong SortedList.
Keys Trả về danh sách các khóa của SortedList.
Values Trả về danh sách các giá trị trong SortedList.

Các phương thức quan trọng của SortedList:

Phương thức Miêu tả
Add(object key, object value) Thêm các cặp khóa và giá trị vào SortedList.
Remove(object key) Xóa phần tử với khóa được chỉ định.
RemoveAt(int index) Xóa phần tử tại vị trí được chỉ định.
Contains(object key) Kiểm tra xem khóa được chỉ định có tồn tại trong SortedList không.
Clear() Xóa tất cả các phần tử khỏi SortedList.
GetByIndex(int index) Trả về giá trị theo chỉ mục được lưu trữ trong mảng nội bộ
GetKey(int index) Trả về khóa được lưu trữ tại chỉ mục được chỉ định trong mảng nội bộ
IndexOfKey(object key) Trả về một chỉ mục của khóa được chỉ định được lưu trữ trong mảng nội bộ
IndexOfValue(object value) Trả về một chỉ mục của giá trị được chỉ định được lưu trữ trong mảng nội bộ

Thêm các phần tử vào SortedList

Sử dụng phương thức Add() để thêm các cặp khóa và giá trị vào SortedList.

Khóa không thể là null và trùng lặp nhưng giá trị có thể là null và trùng lặp. Ngoài ra, kiểu dữ liệu của tất cả các khóa phải giống nhau, để nó có thể so sánh nếu không nó sẽ ném ngoại lệ lúc thực thi (runtime).

Ví dụ sau minh họa thêm phần tử vào SortedList:

SortedList sortedList1 = new SortedList();
sortedList1.Add(3, "Three");
sortedList1.Add(4, "Four");
sortedList1.Add(1, "One");
sortedList1.Add(5, "Five");
sortedList1.Add(2, "Two");

SortedList sortedList2 = new SortedList();
sortedList2.Add("one", 1);
sortedList2.Add("two", 2);
sortedList2.Add("three", 3);
sortedList2.Add("four", 4);
    
SortedList sortedList3 = new SortedList();
sortedList3.Add(1.5, 100);
sortedList3.Add(3.5, 200);
sortedList3.Add(2.4, 300);
sortedList3.Add(2.3, null);
sortedList3.Add(1.1, null);
Thêm phần tử vào SortedList
Lưu ý: Trong nội bộ, SortedList duy trì hai mảng object[], một cho các khóa và một cho các giá trị. Vì vậy, khi bạn thêm một cặp khóa và giá trị, nó sẽ chạy một tìm kiếm nhị phân bằng cách sử dụng khóa để tìm một chỉ mục thích hợp để lưu trữ khóa và giá trị trong các mảng tương ứng. Nó cũng tự động sắp xếp lại các phần tử khi bạn xóa các phần tử khỏi nó.

SortedList sắp xếp lại các phần tử mỗi khi bạn thêm các phần tử. Vì vậy, nếu bạn debug ví dụ trên, bạn sẽ tìm thấy các khóa theo thứ tự tăng dần ngay cả khi chúng được thêm ngẫu nhiên, như dưới đây:

SortedList trong chế độ debug

Xin lưu ý rằng sortList2 sắp xếp khóa theo thứ tự bảng chữ cái cho khóa chuỗi trong hình trên.

Ví dụ minh họa khởi tạo SortedList:

SortedList sortedList = new SortedList()
{
    {3, "Three"},
    {4, "Four"},
    {1, "One"},
    {5, "Five"},
    {2, "Two"}
};

Khóa SortedList có thể thuộc bất kỳ loại dữ liệu nào, nhưng bạn không thể thêm các khóa thuộc các loại dữ liệu khác nhau trong cùng một SortedList. Kiểu dữ liệu của khóa của cặp khóa và giá trị đầu tiên giữ nguyên cho tất cả các cặp khóa và giá trị khác.

Ví dụ sau đây sẽ ném ra ngoại lệ lúc thực thi vì chúng tôi đang cố gắng thêm phần tử thứ hai bằng khóa chuỗi:

SortedList sortedList = new SortedList();

sortedList.Add(3, "Three");
sortedList.Add("Four", "Four"); // Throw exception: InvalidOperationException
sortedList.Add(1, "One");
sortedList.Add(8, "Five");
sortedList.Add(2, "Two");

Truy cập các phần tử trong SortedList

Có thể truy cập các phần tử của SortedList bằng chỉ mục hoặc khóa. Không giống như các collection khác, SortedList yêu cầu khóa thay vì chỉ mục để truy cập một giá trị cho khóa đó.

Ví dụ sau minh họa truy cập giá trị trong SortedList:

SortedList sortedList = new SortedList()
{
	{"one", 1},
	{"two", 2},
	{"three", 3},
	{"four", "Four"}
};

int i = (int) sortedList["one"];
int j = (int) sortedList["two"];
string str = (string) sortedList["four"];

Console.WriteLine(i);
Console.WriteLine(j);
Console.WriteLine(str);

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

1
2
Four
Lưu ý: SortedList non-generic có thể chứa khóa và giá trị của bất kỳ kiểu 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.

Ví dụ sau minh họa sử dụng vòng lặp for để truy cập các phần tử của SortedList:

SortedList sortedList = new SortedList()
{
	{3, "Three"},
	{4, "Four"},
	{1, "One"},
	{5, "Five"},
	{2, "Two"}
};

int length = sortedList.Count;
for (int i = 0; i < length; i++)
{
    Console.WriteLine("key: {0}, value: {1}", 
        sortedList.GetKey(i), sortedList.GetByIndex(i));
}

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

key: 1, value: One
key: 2, value: Two
key: 3, value: Three
key: 4, value: Four
key: 5, value: Five

Câu lệnh foreach cũng có thể được sử dụng để truy cập các phần tử của SortedList. SortedList bao gồm các cặp khóa và giá trị. Vì vậy, kiểu dữ liệu của mỗi phần tử sẽ là DictionaryEntry chứ không phải là kiểu dữ liệu của khóa hoặc giá trị.

SortedList sortedList = new SortedList()
{
	{3, "Three"},
	{4, "Four"},
	{1, "One"},
	{5, "Five"},
	{2, "Two"}
};

foreach(DictionaryEntry item in sortedList)
{
    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: 1, value: One
key: 2, value: Two
key: 3, value: Three
key: 4, value: Four
key: 5, value: Five

Xóa các phần tử khỏi SortedList

Sử dụng phương thức Remove() hoặc RemoveAt() để xóa các phần tử khỏi SortedList.

Ví dụ dưới đây minh họa xóa các phần tử khỏi SortedList:

SortedList sortedList = new SortedList();
sortedList.Add("one", 1);
sortedList.Add("two", 2);
sortedList.Add("three", 3);
sortedList.Add("four", 4);
    
sortedList.Remove("one");//removes element whose key is 'one'
sortedList.RemoveAt(0);//removes element at zero index i.e first element: four

foreach(DictionaryEntry item in sortedList )
{
    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: three, value: 3
key: two, value: 2

Kiểm tra khóa và giá trị tồn tại trong SortedList

Các phương thức Contains()ContainsKey() xác định xem khóa được chỉ định có tồn tại trong SortedList hay không.

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

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

SortedList sortedList = new SortedList();
{
	{3, "Three"},
	{4, "Four"},
	{1, "One"},
	{8, "Eight"},
	{2, "Two"}
};

Console.WriteLine(sList.Contains(2)); // returns true
Console.WriteLine(sList.Contains(4)); // returns true
Console.WriteLine(sList.Contains(6)); // returns false

Console.WriteLine(sList.ContainsKey(2)); // returns true
Console.WriteLine(sList.ContainsKey(6)); // returns false

Console.WriteLine(sList.ContainsValue("One")); // returns true
Console.WriteLine(sList.ContainsValue("Ten")); // returns false

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

True
True
False
True
False
True
False

Truy cập MSDN để biết thêm thông tin về các thuộc tính và phương thức của SortedList.

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

  • C# có SortedList generic và non-generic.
  • SortedList lưu trữ các cặp khóa và giá trị theo thứ tự tăng dần của khóa. Khóa phải là duy nhất và không thể là null trong khi giá trị có thể là null hoặc trùng lặp.
  • SortedList non-generic lưu trữ các khóa và giá trị của bất kỳ loại dữ liệu nào. Vì vậy, các giá trị cần phải được chuyển sang loại dữ liệu thích hợp.
  • Cặp khóa và giá trị có thể được chuyển sang kiểu DictionaryEntry.
  • Truy cập giá trị của một phần tử bằng cách sử dụng bộ chỉ mục. Bộ chỉ mục của SortedList nhận vào giá trị khóa và trả về giá trị được liên kết với nó.

Ở hướng dẫn tiếp theo chúng ta sẽ tìm hiểu về Hashtable - cũng là một non-generic collection như SortedList, cũng lưu trữ các cặp khóa - giá trị.

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


Bài viết liên quan:

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.

Reflection trong C#

  • 6 min read

Reflection trong C# là gì? Ứng dụng của Reflection trong C#. Cách khai báo và sử dụng Reflection trong C#.

Attribute trong C#

  • 7 min read

Attribute trong C# là gì? Có những loại attribute nào trong C#? Làm sao để sử dụng attribute trong C#.