-
常用集合:List、Dictionary、HashSet
常用集合:List、Dictionary、HashSet
概述
集合是C#中用于存储多个数据的容器,相比数组(固定长度、类型单一),集合具有vb.net教程C#教程python教程SQL教程access 2010教程动态扩容、类型安全、功能丰富等优势。本节聚焦三个最常用的泛型集合:
List
Dictionary<TKey, TValue>:键值对集合,通过键快速查找值;
HashSet
-
List
:动态数组
List是泛型动态数组,可自动扩容,支持索引访问、添加/删除元素等操作,是日常开发中最常用的集合之一。
1.1 实例代码:管理学生姓名
csharp
using System;
using System.Collections.Generic;
class Program
{
static void Main()
{
// 1. 初始化List:指定存储string类型,初始容量为5(可选,优化性能)
List<string> students = new List<string>(5);
// 2. 添加元素到末尾
students.Add("张三");
students.Add("李四");
students.Add("王五");
// 3. 插入元素到指定位置(索引1)
students.Insert(1, "赵六");
// 4. 访问元素(通过索引)
Console.WriteLine("索引2的学生:" + students[2]); // 输出:李四
// 5. 修改元素(通过索引)
students[3] = "王麻子";
// 6. 删除元素(按值删除第一个匹配项)
students.Remove("张三");
// 7. 遍历元素(foreach)
Console.WriteLine("
遍历学生列表:");
foreach (string name in students)
{
Console.WriteLine(name); // 输出:赵六、李四、王麻子
}
// 8. 遍历元素(for循环,通过索引)
Console.WriteLine("
通过索引遍历:");
for (int i = 0; i < students.Count; i++)
{
Console.WriteLine($"索引{i}:{students[i]}");
}
// 9. 查找元素(Lambda表达式)
string foundStudent = students.Find(name => name.StartsWith("李"));
Console.WriteLine("
找到以'李'开头的学生:" + foundStudent); // 输出:李四
}
}
1.2 逐行讲解
初始化:List
添加元素:Add在末尾添加,Insert(1, "赵六")在索引1位置插入(后续元素后移);
访问/修改:通过索引students[2]访问,直接赋值修改;
删除:Remove("张三")删除第一个匹配的元素;
遍历:foreach适合简单遍历,for循环适合需要索引的场景;
查找:Find方法用Lambda表达式查找第一个符合条件的元素(如以“李”开头)。
1.3 基础知识拓展
容量与性能优化
List的容量(Capacity)是当前可容纳的最大元素数,计数(Count)是实际元素数。当Count > Capacity时,List会自动扩容(默认翻倍),这会消耗性能。如果提前知道元素数量,初始化时指定容量可优化:
csharp
// 预计存储100个学生,直接指定容量
List
常用方法
RemoveAt(int index):删除指定索引的元素;
Sort():对元素排序(需实现IComparable
ToArray():转换为数组;
Clear():清空所有元素。
-
Dictionary<TKey, TValue>:键值对集合
Dictionary是泛型键值对集合,通过键(Key)快速查找值(Value),键具有唯一性(不可重复)。
2.1 实例代码:存储学生ID与姓名
csharp
using System;
using System.Collections.Generic;
class Program
{
static void Main()
{
// 1. 初始化Dictionary:键为int(学生ID),值为string(姓名)
Dictionary<int, string> studentDict = new Dictionary<int, string>();
// 2. 添加键值对(键唯一,重复会抛异常)
studentDict.Add(101, "张三");
studentDict.Add(102, "李四");
studentDict.Add(103, "王五");
// 3. 安全添加(避免重复键异常)
bool added = studentDict.TryAdd(104, "赵六");
Console.WriteLine("是否添加成功:" + added); // 输出:True
// 4. 访问值(通过键)
Console.WriteLine("ID102的姓名:" + studentDict[102]); // 输出:李四
// 5. 修改值(通过键赋值)
studentDict[103] = "王麻子";
// 6. 删除键值对(通过键)
studentDict.Remove(101);
// 7. 遍历键值对
Console.WriteLine("
遍历键值对:");
foreach (KeyValuePair<int, string> kvp in studentDict)
{
Console.WriteLine($"ID:{kvp.Key},姓名:{kvp.Value}");
}
// 8. 安全获取值(避免键不存在异常)
bool found = studentDict.TryGetValue(105, out string nameOut);
Console.WriteLine("
是否找到ID105:" + found); // 输出:False
Console.WriteLine("获取的姓名:" + nameOut); // 输出:null
}
}
2.2 逐行讲解
初始化:Dictionary<int, string>指定键为int、值为string;
添加:Add方法要求键唯一,TryAdd更安全(返回是否添加成功);
访问/修改:通过键studentDict[102]访问值,直接赋值修改;
删除:Remove(101)通过键删除整个键值对;
遍历:KeyValuePair同时获取键和值,也可单独遍历Keys或Values;
安全获取:TryGetValue避免键不存在时抛出KeyNotFoundException。
2.3 基础知识拓展
键的要求
Dictionary的键必须是不可变类型(如int、string),因为键的哈希码(用于快速查找)不能改变。如果用自定义类型作为键,需重写GetHashCode和Equals方法:
csharp
public class StudentKey
{
public int Id { get; }
public StudentKey(int id) => Id = id;
// 重写哈希码(基于Id)
public override int GetHashCode() => Id.GetHashCode();
// 重写Equals(判断Id是否相等)
public override bool Equals(object obj) => obj is StudentKey key && Id == key.Id;
}
性能优势
Dictionary的查找速度是O(1)(几乎瞬间),因为基于哈希表实现:通过键的哈希码直接定位值,比List的Contains(O(n))快得多。
-
HashSet
:无重复元素的集合
HashSet是无重复元素的泛型集合,基于哈希表实现,适合去重和集合运算(交集、并集、差集)。
3.1 实例代码:存储不重复数字
csharp
using System;
using System.Collections.Generic;
class Program
{
static void Main()
{
// 1. 初始化HashSet:存储int类型
HashSet<int> numbers = new HashSet<int>();
// 2. 添加元素(自动去重)
numbers.Add(1);
numbers.Add(2);
numbers.Add(3);
numbers.Add(2); // 重复元素,自动忽略
// 3. 判断元素是否存在(O(1)时间复杂度)
bool has2 = numbers.Contains(2);
Console.WriteLine("是否包含2:" + has2); // 输出:True
// 4. 删除元素
numbers.Remove(3);
// 5. 遍历元素
Console.WriteLine("
遍历HashSet:");
foreach (int num in numbers)
{
Console.WriteLine(num); // 输出:1、2
}
// 6. 集合运算(交集、并集、差集)
HashSet<int> setA = new HashSet<int> { 1, 2, 3, 4 };
HashSet<int> setB = new HashSet<int> { 3, 4, 5, 6 };
// 交集(共同元素)
setA.IntersectWith(setB);
Console.WriteLine("
交集(A∩B):");
foreach (int num in setA) Console.WriteLine(num); // 输出:3、4
// 重置setA
setA = new HashSet<int> { 1, 2, 3, 4 };
// 并集(所有元素,去重)
setA.UnionWith(setB);
Console.WriteLine("
并集(A∪B):");
foreach (int num in setA) Console.WriteLine(num); // 输出:1、2、3、4、5、6
}
}
3.2 逐行讲解
初始化:HashSet
添加:Add方法自动忽略重复元素(如第二次添加2无效);
判断存在:Contains方法速度极快(O(1));
遍历:用foreach遍历(无索引,因为元素无序);
集合运算:IntersectWith(交集)、UnionWith(并集)、ExceptWith(差集)直接修改原集合。
3.3 基础知识拓展
与List的区别
| 特性 |
List |
HashSet |
|---|---|---|
| 重复元素 | 允许 | 禁止 |
| 索引访问 | 支持 | 不支持 |
| Contains速度 | O(n)(慢) | O(1)(快) |
| 集合运算 | 无内置方法 | 支持(交集、并集等) |
适用场景
需要去重时:如存储用户输入的不重复关键词;
判断元素是否存在时:如验证用户名是否已注册;
集合运算时:如计算两个用户群体的共同兴趣。
总结
三个集合的核心适用场景:
List
Dictionary<TKey, TValue>:需要键值映射、快速查找的场景(如存储用户ID与信息);
HashSet
掌握这三个集合,可解决80%以上的C#数据存储问题。
(本节完)
下一章:LINQ进阶:分组与连接查询
(深入讲解GroupBy、Join等复杂LINQ操作)
本站原创,转载请注明出处:https://www.xin3721.com/ArticlecSharp/c49381.html










