文章目录
- 基本用法
- 主要属性和方法
- 注意事项
- `SortedList` 的一些高级用法和注意事项。
- 自定义排序规则
- 线程安全性
- 性能考量
- 与其他集合的对比
SortedList
是 C# 中的一个集合类,它是一个键/值对集合,其中的键自动按顺序排序。这个类位于
System.Collections.Generic
命名空间中(对于非泛型版本则是
System.Collections
),并且在内部使用一种类似二叉树的结构来高效地维护排序状态。
基本用法
首先,你需要创建一个 SortedList
实例。这里是一个基本的使用示例:
using System;
using System.Collections.Generic;
class Program
{
static void Main()
{
// 创建一个空的 SortedList,键为 int 类型,值为 string 类型
SortedList<int, string> sortedList = new SortedList<int, string>();
// 添加元素
sortedList.Add(3, "Three");
sortedList.Add(1, "One");
sortedList.Add(2, "Two");
// 尝试添加重复键,这将会替换原有的值
sortedList[1] = "First"; // 这里会把键为1的值改为"First"
// 遍历 SortedList
foreach (var pair in sortedList)
{
Console.WriteLine($"Key: {pair.Key}, Value: {pair.Value}");
}
// 访问特定键的值
string value = sortedList[1];
Console.WriteLine($"Value for key 1: {value}");
// 检查键是否存在
bool containsKey = sortedList.ContainsKey(4);
Console.WriteLine($"Contains key 4? {containsKey}");
// 获取键集合或值集合
var keys = sortedList.Keys;
var values = sortedList.Values;
Console.WriteLine("Keys:");
foreach (var key in keys)
{
Console.Write($"{key} ");
}
Console.WriteLine("\nValues:");
foreach (var val in values)
{
Console.Write($"{val} ");
}
}
}
主要属性和方法
- Add(key, value): 向集合中添加一个新的键/值对。如果键已经存在,则会抛出异常。
- this[key]: 索引器,可以用来获取或设置与指定键关联的值。如果键不存在且尝试设置值,会自动添加新的键/值对。
- ContainsKey(key): 检查集合是否包含指定的键。
- Count: 获取集合中的键/值对数量。
- Keys: 获取包含集合中所有键的 ICollection 视图。
- Values: 获取包含集合中所有值的 ICollection 视图。
- Remove(key): 从集合中移除具有指定键的元素。
- Clear(): 移除集合中的所有元素。
注意事项
SortedList
要求其键实现IComparable
接口,以便确定排序顺序。如果键类型不实现此接口,你可能需要提供一个比较器IComparer
。- 对于大量数据的排序操作,应考虑性能影响。虽然
SortedList
提供了快速的查找性能(O(log n) 查找时间复杂度),但频繁的插入和删除可能会较慢,因为它需要调整内部结构以保持排序。
泛型版本的 SortedList<TKey, TValue>
提供了类型安全,并且允许你在创建集合时指定键和值的具体类型。
SortedList
的一些高级用法和注意事项。
自定义排序规则
默认情况下,SortedList
根据键的自然排序顺序进行排序。但是,如果你想要自定义排序逻辑,可以通过提供一个实现了 IComparer<T>
接口的比较器类来实现。
下面是一个如何使用自定义比较器的例子:
using System;
using System.Collections.Generic;
// 自定义比较器类
public class CustomComparer : IComparer<string>
{
public int Compare(string x, string y)
{
// 这里我们按字符串长度进行排序
return x.Length.CompareTo(y.Length);
}
}
class Program
{
static void Main()
{
// 使用自定义比较器创建 SortedList
SortedList<string, string> sortedList = new SortedList<string, string>(new CustomComparer());
sortedList.Add("Apple", " Fruit");
sortedList.Add("Banana", "Fruit");
sortedList.Add("Cherry", "Fruit");
foreach (var pair in sortedList)
{
Console.WriteLine($"Key: {pair.Key}, Value: {pair.Value}");
}
}
}
在这个例子中,SortedList
会根据字符串的长度而不是字母顺序进行排序。
线程安全性
SortedList
类本身并不是线程安全的。这意味着在多线程环境下,如果不采取额外措施,直接对其进行读写操作可能会引发并发问题。如果需要在多线程环境中使用 SortedList
,建议使用锁(如 lock
语句)或其他同步机制来确保线程安全。
性能考量
- 插入和删除:尽管查找操作是高效的(O(log n)),但插入和删除操作可能需要 O(n) 时间,因为它们可能涉及到内部结构的重新平衡。
- 内存占用:由于
SortedList
需要维护元素的排序,它通常比非排序集合(如Dictionary
)占用更多的内存。 - 遍历:遍历
SortedList
时,元素将按照键的排序顺序返回,这对于需要有序输出的场景非常有用。
与其他集合的对比
- 相较于
Dictionary<TKey, TValue>
,SortedList
提供了按键排序的功能,但牺牲了一定的插入和删除性能。 - 如果不需要键的排序功能,且关心性能,特别是在插入和删除操作较多的情况下,
Dictionary<TKey, TValue>
可能是更好的选择。 - 如果只需要键的排序而不需要快速的插入和删除,还可以考虑使用
SortedDictionary<TKey, TValue>
,它在许多情况下提供了更好的性能特性。
总之,SortedList
是一个强大且灵活的集合类,特别适合那些需要高效查找且维持元素排序的场景。理解其特性和限制,能够帮助你更有效地在项目中使用它。
一个实际的应用案例是假设你正在开发一个简单的联系人管理应用程序,需要存储并显示按照姓名排序的联系人列表。SortedList
可以完美地应用于此场景,因为它可以自动保持联系人的姓名排序,使得查询和展示变得高效且直观。
以下是一个简化的联系人管理应用示例:
using System;
using System.Collections.Generic;
class Contact
{
public string Name { get; set; }
public string PhoneNumber { get; set; }
public override string ToString()
{
return $"Name: {Name}, Phone: {PhoneNumber}";
}
}
class ContactManager
{
private SortedList<string, Contact> contactsByName;
public ContactManager()
{
contactsByName = new SortedList<string, Contact>();
}
public void AddContact(Contact contact)
{
contactsByName.Add(contact.Name, contact);
}
public void RemoveContact(string name)
{
contactsByName.Remove(name);
}
public Contact GetContact(string name)
{
contactsByName.TryGetValue(name, out Contact contact);
return contact;
}
public void DisplayContacts()
{
foreach (var contact in contactsByName.Values)
{
Console.WriteLine(contact);
}
}
}
class Program
{
static void Main(string[] args)
{
ContactManager manager = new ContactManager();
manager.AddContact(new Contact { Name = "Alice", PhoneNumber = "123-456-7890" });
manager.AddContact(new Contact { Name = "Bob", PhoneNumber = "234-567-8901" });
manager.AddContact(new Contact { Name = "Charlie", PhoneNumber = "345-678-9012" });
Console.WriteLine("Contacts:");
manager.DisplayContacts();
// 删除一个联系人
manager.RemoveContact("Bob");
Console.WriteLine("\nContacts after removing Bob:");
manager.DisplayContacts();
// 查询一个联系人
Contact charlie = manager.GetContact("Charlie");
if (charlie != null)
{
Console.WriteLine($"\nFound Charlie: {charlie}");
}
}
}
在这个例子中,我们创建了一个 Contact
类来表示联系人信息,并使用 SortedList<string, Contact>
来存储联系人,其中键是联系人的姓名,值是联系人对象。这样,当我们添加、删除或查询联系人时,SortedList
都能自动保证按照姓名的字母顺序排列。通过 DisplayContacts
方法,我们可以直接遍历并打印出按顺序排列的所有联系人信息。
————————————————
最后我们放松一下眼睛