C# 各类集合用法汇总【全面示例各种方法】

1、ArrayList

特点:不定长度的,大小可根据需要自动扩充,内存连续分配的。

ArrayList是一个可动态维护是长度的集合,又称动态数组,它不限制元素的个数和数据类型,允许把任意类型的数据保存到ArrayList中。数组类Array与动态数组类ArrayList的区别主要如下:
(1)Array的大小是固定的,而ArrayList的大小可根据需要自动扩充。
(2)在Array中一次只能读写一个元素的值,而ArrayList允许添加、插入或移除某一范围的元素。
(3)Array的下限可以自定义,而ArrayList的下限始终为0。
(4)Array可以有多个维度,而ArrayList始终是一维的。
(5)Array位于System命名空间中,ArrayList位于System.Collections命名空间中。
需要注意的是:ArrayList会动态调整索引,在删除一个元素后,该元素后面的索引值会自动减少1。
由于可变数组在使用foreach循环遍历的时候会被锁定,一边遍历一边删除会出现问题,可能会抛出ConcurrentModificationException异常
解决办法:
以下三种方式是比较常规的解决办法:
一、迭代器删除
利用iterator自带的remove方法进行删除,由于iterator.remove()方法删除时会自动进行数组下进行移位操作。
public static void iterator(ArrayList list) {
Iterator it = list.iterator();
while (it.hasNext()) {
Long a = it.next();
if (a == 3) {
it.remove();
}
}
System.out.println(list);
二、for循环倒序删除
for循环正序删除也可以,只不过每删除一个元素,数组的list.size()会立刻发生改变,可能会导致删除不干净。【也可以通过每删除一次对i–一次】
public static void backDel(ArrayList list) {
for (int i = list.size() - 1; i > 0; i–) {
if (list.get(i) == 3) {
list.remove(i);
}
}
System.out.println(list);
}
三、lambda表达式删除
public static void lambda(ArrayList list) {
ArrayList delList = new ArrayList<>();
list.stream().forEach(vo -> {
if (vo == 3) {
delList.add(vo);
}
});
list.removeAll(delList);
System.out.println(list);
}
————————————————

基础用法:

//定义一个 集合,集合是一个类,在using System.Collections库中,需要引用
ArrayList al = new ArrayList();  
//Array[] array = new Array();会报错,数组要定义大小才可以使用 应为Array[] array = new Array[2];

//给ArrayList 集合赋值
ArrayList al2 = new ArrayList() { 3,7,8,"hello",4.56};

//元素没有类型限制 任何元素都当成object处理
al.Add("object");//末尾添加元素

//逗号前面的是索引号,逗号后面的是数据(当集合中有三个数据,插入的索引号为1时,则原为1索引号的数据将为2,后面的依次往后退一位)
al.Insert( 1,"abc" );

//括号内填的是集合中要移除的数据(在移除中若集合中有两个重复的数 .Remove() 只移除第一次出现的数)
al.Remove("object");

//括号内填的是集合中要移除的数据的索引号
al.RemoveAt(3);

int n = al.Count;//获取集合中元素的个数

int s = al.IndexOf("object");       //括号中是要找的元素,这个元素第一次出现的索引号

int s1 = al.LastIndexOf("object");  //括号中是要找的元素,这个元素最后一次出现的索引号

al.Sort();//这是升序排序,降序排序的话要在升序排序方法后用翻转(翻转———   al.Reverse();

al.Clear();  //清空集合

//复制集合中的元素数据,装入新的集合当中
ArrayList xal = new ArrayList();
xal = (ArrayList)al.Clone();

//判断一个集合里面是不是包含这个元素数据返回bool值
bool b = al.Contains();//括号内为要查找是否集合包含的元素

var objArr= al.ToArray(al2);//将ArrayList里面的元素复制到数组中

al.AddRange(al2); //将al2集合添加到al末尾

int c = al.Capacity;//ArrayList的容量,初始容量为4,扩容后为原来的两倍

Array copyArray = new Array[al.Count];
al.CopyTo(copyArray);//将al集合的元素对象拷贝到数组copyArray中

Func<string, int> func = m => 1;
al.Add(func);//可以放Delegate

注意:频繁的调用IndexOf、Contains等方法(Sort、BinarySearch等方法经过优化,不在此列)引起的效率损失

遍历ArrayList

 ArrayList al = new ArrayList();
 //添加元素....略
 
 //第一种遍历ArrayList的方法
 Console.WriteLine("第一种遍历ArrayList的方法:");
 foreach (int i in al)
	{
         Console.Write(i + " ");
	}
//第二种遍历ArrayList的方法
 Console.WriteLine("第二种遍历ArrayList的方法:");
 for(int i = 0; i < al.Count; i++)
 {
 	 Console.Write(al[i].ToString() + " "); 
 }

//第三种遍历ArrayList的方法
 Console.WriteLine("第三种遍历ArrayList的方法:");
 IEnumerator ie=arr.GetEnumerator();//迭代器:具体解析在代码下面有
 while(ie.MoveNext())
 {
    Console.Write(ie.Current.ToString()+" ");
 }

IEnumberator,枚举器(迭代器) , 字面意思,用来一个一个枚举。
其关键成员有:当前对象current,是否有下一个movenext
IEnumerable,可枚举的, 字面意思,继承了我就变成了一个可枚举的对象。
其只有一个成员 GetEnumerator,返回枚举器类型。

2、泛型List

List和ArrayList的区别
1.list性能较高,ArrayList性能较低
2.list一次存储中只能存储泛型中的类型,ArrayList在一次存储中任何类型的数据
3.List中获取值取出的是泛型中发的类型,因为ArrayList对元素没有限制,系统会将中获取的值当object类型的数据, 如果想获取到其中的内容需要进行
4. List在使用时候需要导入的using指令为using System.Collections.Generic; ArrayList在使用的时候需要导入的using指令为using System.Collections;
5.List属于泛型集合 ArrayList属于非泛型集合
6.List 是个强类型,很安全。其次看那个尖括号,它是 C#2.0 时加入的泛型,所以并不存在像 ArrayList要拆/装箱以此造成性能浪费。

利用System.Collections.Generic命名空间下面的List泛型类创建集合,语法如下:

List<T> lst= new List<T>();

其中的"T"就是所要使用的类型,既可以是简单类型,如string、int,也可以是用户自定义类型。

常用方法:

Count 属性,用于获取数组中当前元素数量
Item( ) 通过指定索引获取或设置元素。对于List类来说,它是一个索引器。
Add( ) 在List中添加一个对象的公有方法
AddRange( ) 公有方法,在List尾部添加实现了ICollection接口的多个元素
BinarySearch( ) 重载的公有方法,用于在排序的List内使用二分查找来定位指定元素.
Clear( ) 在List内移除所有元素
Contains( ) 测试一个元素是否在List内
CopyTo( ) 重载的公有方法,把一个List拷贝到一维数组内
Exists( ) 测试一个元素是否在List内
Find( ) 查找并返回List内的出现的第一个匹配元素
FindAll( ) 查找并返回List内的所有匹配元素
GetEnumerator( ) 重载的公有方法,返回一个用于迭代List的枚举器
Getrange( ) 拷贝指定范围的元素到新的List内
IndexOf( ) 重载的公有方法,查找并返回每一个匹配元素的索引
Insert( ) 在List内插入一个元素
InsertRange( ) 在List内插入一组元素
LastIndexOf( ) 重载的公有方法,,查找并返回最后一个匹配元素的索引
Remove( ) 移除与指定元素匹配的第一个元素
RemoveAt( ) 移除指定索引的元素
RemoveRange( ) 移除指定范围的元素
Reverse( ) 反转List内元素的顺序
Sort( ) 对List内的元素进行排序
ToArray( ) 把List内的元素拷贝到一个新的数组内
trimToSize( ) 将容量设置为List中元素的实际数目

List的基础、常用方法:

(1)、声明:
①、List<T> mList = new List<T>();
T为列表中元素类型,现在以string类型作为例子

List<string> mList = new List<string>();

②、List<T> testList =new List<T> (IEnumerable<T> collection);
以一个集合作为参数创建List:

string[] temArr = { "Ha", "Hunter", "Tom", "Lily", "Jay", "Jim", "Kuku", "Locu" };
List<string> testList = new List<string>(temArr);

(2)、添加元素:
①、添加一个元素
语法: List. Add(T item)

List<string> mList = new List<string>();
mList.Add("John");

②、添加一组元素
语法: List. AddRange(IEnumerable<T> collection)

List<string> mList = new List<string>();
string[] temArr = { "Ha","Hunter", "Tom", "Lily", "Jay", "Jim", "Kuku",  "Locu" };
mList.AddRange(temArr);

③、在index位置添加一个元素
语法:Insert(int index, T item);

List<string> mList = new List<string>();
mList.Insert(1, "Hei");

④、遍历List中元素
语法:

foreach (T element in mList)  //T的类型与mList声明时一样
{
    Console.WriteLine(element);
}

例:

List<string> mList = new List<string>();
...//省略部分代码
foreach (string s in mList)
{
    Console.WriteLine(s);
}

(3)、删除元素:
①、删除一个值
语法:List. Remove(T item)

mList.Remove("Hunter");

②、 删除下标为index的元素
语法:List. RemoveAt(int index);

mList.RemoveAt(0);

③、 从下标index开始,删除count个元素
语法:List. RemoveRange(int index, int count);

mList.RemoveRange(3, 2);

(4)、判断某个元素是否在该List中:
语法:List. Contains(T item) 返回值为:true/false

if (mList.Contains("Hunter"))
{
    Console.WriteLine("There is Hunter in the list");
}
else
{
    mList.Add("Hunter");
    Console.WriteLine("Add Hunter successfully.");
}

(5)、给List里面元素排序:
语法: List. Sort () 默认是元素第一个字母按升序

mList.Sort();

自定义规则排序

/// <summary>
///①通用自定义
/// </summary>
list.Sort((left, right) =>
{
    if (left.n > right.n)//其中 n 是某个你希望以此进行排序的属性//此时按 n 由小到大的顺序排序; 若想由大到小排列,此处改为  left.n < right.n
        return 1;
    else if (left.n == right.n)
        return 0;
    else
        return -1;
});

/// <summary>
/// ②针对属性是字符串的排序
/// </summary>
list.Sort((left, right) =>
{
    return left.Date.CompareTo(right.Date);//其中Date是时间字符串             
});

(6)、给List里面元素顺序反转:
语法:List. Reverse () 可以与List. Sort ()配合使用,达到想要的效果

mList. Reverse();

(7)、List清空:
语法:List. Clear ()

mList.Clear();

(8)、获得List中元素数目:
语法: List. Count () 返回int值

int count = mList.Count();
Console.WriteLine("The num of elements in the list: " +count);

2、List的进阶、强大方法:
本段举例用的List:

string[] temArr = { "Ha","Hunter", "Tom", "Lily", "Jay", "Jim", "Kuku", " "Locu" };
mList.AddRange(temArr);

(1)、List.FindAll方法:检索与指定谓词所定义的条件相匹配的所有元素
语法:public List<T> FindAll(Predicate<T> match);

List<string> subList = mList.FindAll(ListFind); //委托给ListFind函数
foreach (string s in subList)
{
    Console.WriteLine("element in subList: "+s);
}

这时subList存储的就是所有长度大于3的元素。

(2)、List.Find 方法:搜索与指定谓词所定义的条件相匹配的元素,并返回整个 List 中的第一个匹配元素。
语法:public T Find(Predicate<T> match);

Predicate是对方法的委托,如果传递给它的对象与委托中定义的条件匹配,则该方法返回 true。当前 List 的元素被逐个传递给Predicate委托,并在 List 中向前移动,从第一个元素开始,到最后一个元素结束。当找到匹配项时处理即停止。

Predicate 可以委托给一个函数或者一个拉姆达表达式:

委托给拉姆达表达式:

string listFind = mList.Find(name =>  //name是变量,代表的是mList中元素,自己设定
{     
   if (name.Length > 3)
   {
      return true;
   }
  return false;
});
Console.WriteLine(listFind);     //输出是Hunter

委托给一个函数:

string listFind1 = mList.Find(ListFind);  //委托给ListFind函数
Console.WriteLine(listFind);    //输出是Hunter
 
//ListFind函数
public bool ListFind(string name)
{
    if (name.Length > 3)
    {
        return true;
    }
    return false;
}

这两种方法的结果是一样的。

(3)、List.FindLast 方法:搜索与指定谓词所定义的条件相匹配的元素,并返回整个 List 中的最后一个匹配元素。
语法:

public T FindLast(Predicate<T> match);

用法与List.Find相同。

(4)、List.TrueForAll方法: 确定是否 List 中的每个元素都与指定的谓词所定义的条件相匹配。
语法:public bool TrueForAll(Predicate<T> match);

委托给拉姆达表达式:

bool flag = mList.TrueForAll(name =>
{
    if (name.Length > 3)
    {
     return true;
    }
    else
    {
     return false;
    }
});
Console.WriteLine("True for all:  "+flag);  //flag值为

委托给一个函数,这里用到上面的ListFind函数:

bool flag = mList.TrueForAll(ListFind);    //委托给ListFind函数
Console.WriteLine("True for all:  "+flag);  //flag值为false

这两种方法的结果是一样的。

(5)List.Take(n)方法: 获得前n行 返回值为IEnumetable,T的类型与List的类型一样

IEnumerable<string> takeList=  mList.Take(5);
foreach (string s in takeList)
{
      Console.WriteLine("element in takeList: " + s);
}

这时takeList存放的元素就是mList中的前5个。

(6)、List.Where方法:检索与指定谓词所定义的条件相匹配的所有元素。跟List.FindAll方法类似。

IEnumerable<string> whereList = mList.Where(name =>
{
   if (name.Length > 3)
   {
      return true;
   }
   else
  {
     return false;
  }
});
 
foreach (string s in subList)
{
   Console.WriteLine("element in subLis");
}

这时subList存储的就是所有长度大于3的元素。

(7)、List.RemoveAll方法:移除与指定的谓词所定义的条件相匹配的所有元素。
语法: public int RemoveAll(Predicate<T> match);

mList.RemoveAll(name =>
{
     if (name.Length > 3)
    {
        return true;
    }
    else
    {
        return false;
    }
});
 
foreach (string s in mList)
{
    Console.WriteLine("element in mList:     " + s);
}

这时mList存储的就是移除长度大于3之后的元素。
(8)List.Except()方法,求两个List的差集
语法: ListA.Except(ListB)。ListA和ListB代表同一类型的类型的List集合数据,返回结果是,在ListA中但是不在ListB中的元素的集合。

List<int> list1 = new List<int> { 1, 2, 3, 4 };
List<int> list2 = new List<int> { 3, 4, 5, 6 };
  
List<int> exceptList = list1.Except(list2).ToList();

运算得到的结果集为:exceptList集合中包含2个元素,为1和2。

3、LinkedList

LinkedList:双向链表 元素不连续分配,每个元素都有记录前后节点。

在这里插入图片描述
链表不能通过元素索引访问。找元素只能遍历。增删比较快,增加或删除,只需把这个元素的前后两个元素指向的元素节点改一下。

//在头部和尾部都标识了上一个元素和下一个元素所处位置
LinkedList<int> list = new LinkedList<int>();
list.AddLast(1);
list.AddFirst(1);
bool isBool = list.Contains(1);//判断链表中是否有1这个元素
 
LinkedListNode<int> list1 = list.Find(123);//找到元素123的这个节点
list.AddBefore(list1, 0);//前面增加
list.AddAfter(list1, 0);//后面增加
 
list.Remove(1);
list.Remove(list1);//根据节点删除
list.RemoveFirst();
list.RemoveLast();
list.Clear();

4、Queue

Queue 队列,就是链表 先进先出

//用处;放任务延迟执行 A不断写入任务,B不断获取任务执行 每次拿最近的一个任务
Queue<string> queue = new Queue<string>();
queue.Enqueue("object");//添加数据
queue.Enqueue("object1");
foreach (var item in queue)
{
 Console.WriteLine(item);
}
queue.Dequeue();//获取最先进入队列的元素,获得并移除
queue.Peek();//获取但不移除

5、Stack

Stack:栈 也是链表, 先进后出 先产生的数据最后使用

Stack<string> stack = new Stack<string>();
stack.Push("object");//添加数据
stack.Push("object1");
stack.Pop();//获取最后进入队列的元素 获得并移除
stack.Peek();//获取不移除
C#中(线程)栈的内存释放也是一样,先实例化的对象最后释放(在栈中声明的变量,最先声明的最后GC)

在这里插入图片描述

Set类型集合

6、HashSet

HashSet:hash分布,元素间没关系(不用记录前后节点),动态增加.

HashSet<string> hashSet = new HashSet<string>();
hashSet.Add("object1");//添加元素
hashSet.Add("object2");
hashSet.Add("object3");
hashSet.Add("object1");//会自动去重
int count = hashSet.Count;//获得数量
hashSet.Contains("object");

HashSet<string> hashSet1 = new HashSet<string>();
hashSet1.Add("object1");
hashSet1.Add("object2");
hashSet1.Add("object4");
hashSet1.SymmetricExceptWith(hashSet);//补集:不包含hashSet1和hashSet共有的所有元素
hashSet1.UnionWith(hashSet);//并集:hashSet1和hashSet所有的元素
hashSet1.ExceptWith(hashSet);//差集:hashSet1有的元素而hashSet没有的元素
hashSet1.IntersectWith(hashSet);//交集:共同的元素
hashSet1.ToList();
hashSet1.Clear();

7、SortedSet

SortedSet:排序集合 去重+排序.SortedSet也可以做交差并补.

//IComparer<T>? comparer 自定义对象要排序,就用这个指定
SortedSet<string> sortedSet = new SortedSet<string>();
sortedSet.Add("object1");
sortedSet.Add("object2");
sortedSet.Add("object1");//会自动去重
int count = sortedSet.Count;
sortedSet.Contains("object1");
HashTable(key-value)类型集合

8、Hashtable:

拿着key计算一个内存地址,然后放入key-value。长度不定,可以动态增加。放入的都是object类型,所以避免不了装箱拆箱。

//如果不同的key得到相同的内存地址,第二个在前面的地址上+1,由此会形成数组
 //查找的时候,如果地址对应的key不对,那就+1查找//查找个数据 一次定位,增删查改都很快
 //数据太多 重复定位,效率就下去了
 Hashtable hashtable = new Hashtable();
 hashtable.Add("key", "value");
 hashtable[111] = 222;//KEY,VALUE
 foreach (DictionaryEntry item in hashtable)
 {
  Console.WriteLine(item.Key.ToString());
  Console.WriteLine(item.Value.ToString());
 }
 //线程安全
 Hashtable.Synchronized(hashtable);//只有一个线程写,多个线程读

9、Dictionary:

相当于泛型版本的HashTable.因为数据基于泛型,减少了装箱拆箱的消耗.

<strong>Dictionary<int, string> pairs = new Dictionary<int, string>();
pairs.Add(1, "object1");
pairs[2] = "object2";
foreach (var item in pairs)
{
 Console.WriteLine(item.Key.ToString(), item.Value);
}
pairs.ContainsKey(1);//是否存在这个key
//... ...</strong>

10、SortedDictionary:

排序字典,依据key进行排序.因为要排序,所以增删改慢,多了一个排序

SortedDictionary<int, string> pairs = new SortedDictionary<int, string>();
//根据key依次排序
pairs.Add(1, "object1");
pairs.Add(2, "object2");
pairs.Add(3, "object3");
pairs.Add(4, "object4");
SortedList:

也是key,value形式,自动排序.不能重复添加,key重复会报错

IComparer comparer 自定义对象要排序,就用这个指定
在这里插入图片描述

SortedList sortedList = new SortedList();
sortedList.Add("2", "1");
var keyList = sortedList.GetKeyList();
var valueList = sortedList.GetValueList();
sortedList.TrimToSize();//用于最小化集合的内存开销
sortedList.Remove("1");//根据key值移除
sortedList.RemoveAt(0);//根据索引移除
sortedList.Clear();//移除所有元素
字典集合线程不安全(非线程安全),这块内存多个线程都可以改
ConcurrentQueue 线程安全版本的Queue
ConcurrentStack 线程安全版本的Stack
ConcurrentBag (List集合是非线程安全的)ConcurrentBag线程安全版本的对象集合
ConcurrentDictionary 线程安全版本的Dictionary
BlockingCollection 线程安全集合

ArrayList和List都实现了IList接口,可以通过索引访问元素,像链表这种就不可以通过索引访问元素.

在这里插入图片描述
但是链表这种集合继承了ICollection类型的接口,因此可获得集合的长度(长度不定的集合都继承了ICollection接口)
在这里插入图片描述

IEnumerable\ICollection\IList\IQueryable
接口是标识功能的.不同的接口拆开就是为了接口隔离.实现不同的接口表明这个集合的功能不同.
任何数据集合都实现IEnumerable,IEnumerable为不同的数据结构(各种集合)提供了统一的数据访问方式(foreach)=》迭代器模式

请添加图片描述

  • 5
    点赞
  • 42
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
课程通过实际项目融入常用开发技术架构,讲授风格独特,提供详细上课日志及答疑,赠送配套的项目架构源码注释详细清晰且表达通俗,均能直接在实际项目中应用,正真的物超所值,价格实惠任务作业:综合运用《C#/.Net企业级系统架构设计实战精讲教程》课程所学知识技能设计一个学生成绩管理系统的架构。要求:1.系统基于MVC的三层架构,各层单独建不同的解决方案文件夹。2.采用Model First开发方式,设计架构时只需要设计学生表(TbStudent)和课程表(TbCourse)。学生表必须有的字段是ID、stuName、age;课程表必须有的字段是ID、courseName、content。3.数据访问层采用Entity Framework或NHibernate来实现,必须封装对上述表的增删改查方法。4.必须依赖接口编程,也就是必须要有数据访问层的接口层、业务逻辑层的接口层等接口层。层层之间必须减少依赖,可以通过简单工厂或抽象工厂。5.至少采用简单工厂、抽象工厂、Spring.Net等技术中的2种来减少层与层之间的依赖等。6.封装出DbSession类,让它拥有所有Dal层实例和SaveChanges方法。7.设计出数据访问层及业务逻辑层主要类的T4模板,以便实体增加时自动生成相应的类。8.表现层要设计相关的控制器和视图来验证设计的系统架构代码的正确性,必须含有验证增删改查的方法。9.开发平台一定要是Visual Studio平台,采用C#开发语言,数据库为SQL Server。10.提交整个系统架构的源文件及生成的数据库文件。(注意: 作业需写在CSDN博客中,请把作业链接贴在评论区,老师会定期逐个批改~~)

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

薪薪代码

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值