数组的长度声明后就是固定的,且都是存的同一种类型的数据。
集合的长度是不固定的(主要特征),可以存不同类型的元素;但泛型集合必须是同一种类型的集合
集合内部的原理用的还是数组,都是依赖于数组的,内部存数据都是存到了数组中。
集合的命名空间
-
using System.Collections;
(非泛型集合) -
using System.Collections.Generic;
(泛型集合)
常用集合
- 类似数组集合:
AraylList、List<T>
- “键值对”集合(“哈希表”集合):
Hashtable
、Dictionary<K,V>
- “堆栈”集合:
Stack
、Stack<T>
(LIFO)Last In First Out - “队列”集合:
Queue
、Queue<T>
(FIFO)First In First Out - “可排序键值对“集合:(插入、检索没有“哈希表”集合高效)
-
SortedlList
、SortedList<K, V>
(占用内存更少,可以通过索引访词) -
SortedDictionary<K,V>
(占用内存更多,没有索引,但插入、删除元素的速度比SortedList
快)
-
-
Set
集合:无序、不重复。HashSet<T>
,可以将HashSet类视为不包含值的Dictionary
集合。与List<T>
类似。SortedSet<T>
(.net4.0支持,有序无重复集合) - “双向链表”集合:
LinkedList<T>
,增删速度快。
增删改查遍历
ArrayList
、Hashtable
、List<T>
、 Dictionary<K,V>
:
- 数组的特点:类型统一、长定固定。
- 集合常用操作添加、遍历、移除
- 命名空间
System.Colections
-
ArayList
可变长度数组,使用类似于数组- 属性
Capacity
(集合中以容纳元素的个数,翻信增长);Count
(集合中实际存放的元素的个数。) - 方法
-
Add(10)
AddRange(ICollection c)
Remove()
RemoveAt()
Clear()
-
Contains()
ToArray()
Sort()
排序Reverse()
//反转
-
- 属性
-
Hashtable
键值对的集合,类似于字典,Hashtable
在查找元素的时候,速度很快。-
Add(object key, object value)
; -
hash["key"]
; -
hash["key"]="修改"
; -
ContainsKey(key)
; -
Remove("key")
; - 遍历;
-
hash.Keys
; -
hasth.Values/Dictionary Entry
; - 键值对集合中的"键",绝对不能重复。
-
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Collections;
namespace 集合
{
static class Program
{
static void Main()
{
ArrayList arrayList = new ArrayList();// 注意提示有几个重载函数。
//向集合中增加元素
arrayList.Add(10); // 传的参数为 object,什么类型都可以。
arrayList.Add("10");
arrayList.Add("张三丰");
Person gj = new Person() {
Name = "郭靖",
};
arrayList.Add(gj); // 添加对象也可以。
// ▼ Count 表示集合中的元素实际个数
Console.WriteLine("集合中存在的元素个数{0}。", arrayList.Count);
// ▼ Capacity 容量,可以理解:容量有 100,实际上可以只放 1 个元素。
Console.WriteLine("集合现在的容量{0}", arrayList.Capacity);
Console.WriteLine("==========传接口类型==========");
// ICollection 接口, ArrayList 自己也可以往里传,数组也可以。所有集合,所有数组都可以传。
// 实现了 ICollection 的类都可以
arrayList.Add(new int[] { 1, 3, 5, 7, 9 });
// 集合获取元素
Console.WriteLine(arrayList[0]);// 用索引器访问
Console.WriteLine(arrayList[3]);
Console.WriteLine("==========for 循环遍历集合==========");
// ▼ for 循环遍历集合
for(int i = 0; i < arrayList.Count; i++) {
// C# 所有集合长度都是 Count,数组都是 Length。
Console.WriteLine(arrayList[i]);
}
// 向指定位置插入一个元素
Console.WriteLine("==========向指定位置插入一个元素==========");
arrayList.Insert(0, "洪七公");// 索引为 0 的位置中插入,以前的依次向后移动
for (int i = 0; i < arrayList.Count; i++) {
// C# 所有集合长度都是 Count,数组都是 Length。
Console.WriteLine(arrayList[i]);
}
// 也可以插一堆的元素
Console.WriteLine("==========向指定位置插入一堆元素==========");
arrayList.InsertRange(3, new string[]{ "a", "good", "moring"});
for (int i = 0; i < arrayList.Count; i++) {
// C# 所有集合长度都是 Count,数组都是 Length。
Console.WriteLine(arrayList[i]);
}
// 删除元素 可以根据 IDE 的提示参数去理解函数的含义
//arrayList.Remove;
//arrayList.RemoveAt;// 根据索引来删除
//arrayList.RemoveRange;// 删除一段,从第几个开始删除到第几个元素,这个比较好理解。
Console.WriteLine("===========删除结果是:=============");
Console.WriteLine(arrayList.Count);
for (int i = 0; i < arrayList.Count; i ++) {
arrayList.RemoveAt(i);
}
Console.WriteLine(arrayList.Count);// 可见,删一个就移动重组一下。
Console.WriteLine("===========清除ArrayList=============");
arrayList.Clear();
Console.WriteLine("集合中存在的元素个数{0}。", arrayList.Count);
// foreach 是只读循环
Console.WriteLine("===========根据对象来删除=============");
// ▼ 根据对象来删除
Person p1 = new Person() {
Name = "雪山飞狐",
Age = 100,
Email = "nb@sina.com.cn"
};
arrayList.Add(p1);
arrayList.Add(99);
arrayList.Add("黄蓉");
Person p2 = new Person() {
Name = "雪山飞狐",
Age = 100,
Email = "nb@sina.com.cn"
};
arrayList.Add(p2);
Console.WriteLine("集合中存在的元素个数{0}。", arrayList.Count);
arrayList.Remove(99);
Person p3 = new Person();
p3.Name = "雪山飞狐";
p3.Age = 100;
p3.Email = "nb@sina.com.cn";
Console.WriteLine("集合中存在的元素个数{0}。", arrayList.Count);
arrayList.Remove(p3);// 这个对象没有添加,也就没有删除,但也没报错
Console.WriteLine("集合中存在的元素个数{0}。", arrayList.Count);
// 如果这样就能删掉
p3 = p1;
arrayList.Remove(p3);// 这个对象没有添加,也就没有删除,但也没报错
Console.WriteLine("集合中存在的元素个数{0}。", arrayList.Count);
// ▲ 这样能删除
string name = new string(new char[] { ‘黄‘, ‘蓉‘});
arrayList.Remove(name); // 删除掉了“黄蓉”
Console.WriteLine("集合中存在的元素个数{0}。", arrayList.Count);
// 总结:
// Remove 并不是按照是不是对象的地址来删除的,而是判断是不是相等来删除的。
Console.WriteLine(arrayList.Contains(99)); // 判断是否包含这个元素
}
}
public class Person
{
public string Name {
get;
set;
}
public int Age {
get;
set;
}
public string Email {
get;
set;
}
}
}
输出:
集合中存在的元素个数4。
集合现在的容量4
==========传接口类型==========
10
集合.Person
==========for 循环遍历集合==========
10
10
张三丰
集合.Person
System.Int32[]
==========向指定位置插入一个元素==========
洪七公
10
10
张三丰
集合.Person
System.Int32[]
==========向指定位置插入一堆元素==========
洪七公
10
10
a
good
moring
张三丰
集合.Person
System.Int32[]
===========删除结果是:=============
9
4
===========清除ArrayList=============
集合中存在的元素个数0。
===========根据对象来删除=============
集合中存在的元素个数4。
集合中存在的元素个数3。
集合中存在的元素个数3。
集合中存在的元素个数2。
集合中存在的元素个数1。
False
请按任意键继续. . .
ArrayList 排序等
要想任意类型实现ArrayList Sort() 排序,需要实现 IComparable 这个接口。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Collections;
namespace ArrayList排序等
{
static class Program
{
static void Main()
{
#region ArrayList 的 sort 方法
ArrayList arr = new ArrayList(new int[] { 1, 3, 26, 9, 10 });
Console.WriteLine("==========升序========");
arr.Sort();// 注意有三个重载
for (int i = 0; i < arr.Count; i++) {
Console.WriteLine(arr[i]);
} // 默认的是升序排序,从小到大.没有降序排序但可以 Reverse
Console.WriteLine("==========降序========");
arr.Reverse(); // 先升序,再反转就成降序了
for (int i = 0; i < arr.Count; i++) {
Console.WriteLine(arr[i]);
}
/*字符串排序*/
ArrayList arrList = new ArrayList(new string[] { "hl", "xzl", "yzk", "fxh","ksjd","" ,"zaz"});
arrList.Sort();
Console.WriteLine("==========字符串排序========");
for (int i = 0; i < arrList.Count; i++) {
Console.WriteLine(arrList[i]);
}
// ▲ 字符串排序,按第一个字母 ASCII 码大小排序。第一个字母比完,第二个字母比,依次比较。
// 升序比较。
Console.WriteLine("==========对象排序========");
ArrayList arrObj = new ArrayList();
Person p1 = new Person() {
Name = "hjk",
Age = 100,
Email = "hhh@andyvj.com"
};
Person p2 = new Person() {
Name = "gdss",
Age = 90,
Email = "sd@andyvj.com"
};
Person p3 = new Person() {
Name = "cbv",
Age = 80,
Email = "ge@andyvj.com"
};
Person p4 = new Person() {
Name = "rtsssy",
Age = 70,
Email = "ghkj@andyvj.com"
};
arrObj.Add(p1);
arrObj.Add(p2);
arrObj.Add(p3);
arrObj.Add(p4);
Console.WriteLine("元素个数:" + arrObj.Count);
arrObj.Sort(); // 对象不能直接按这个排,因为不知道按什么排
// 对象需要继承 IComparable 接口实现 CompareTo方法
for (int i = 0; i < arrObj.Count; i++) {
Console.WriteLine(((Person)arrObj[i]).Name); // 装箱成对象了,要强制转一下。
}
// 想要 Sort 排序,数据类型必须是实现过 IComparable 这个接口的
// 所以 Person 对象想要排序,就必须要实现 IComparable 这个接口
#endregion
}
public class Person: IComparable
{
public string Name {
get;
set;
}
public int Age {
get;
set;
}
public string Email {
get;
set;
}
// ▼ IComparable 接口实现 CompareTo方法
public int CompareTo(object obj)
{
Person p = obj as Person;
if (p != null) {
/*
return this.Age - p.Age; // 升序降序在这里改下相减的前后顺序
// ▲ 按照年龄,大 > 0,等 = 0, 小 < 0
*/
return this.Name.Length - p.Name.Length; // 按名字的长度排序
}
return 0;
}
// 总结:要想任意类型实现ArrayList Sort() 排序,需要实现 IComparable 这个接口。
}
}
}
输出:
==========升序========
1
3
9
10
26
==========降序========
26
10
9
3
1
==========字符串排序========
fxh
hl
ksjd
xzl
yzk
zaz
==========对象排序========
元素个数:4
hjk
cbv
gdss
rtsssy
请按任意键继续. . .
ArrayList 任何情况排序
总结:如果要升序再写一个类实现 IComparer,如果按年龄再写一个类实现IComparer,依次… 有多少个情况。
就写多少个比较的类就行了,不用去改源代码。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Collections;
namespace Arralist随意排序
{
static class Program
{
static void Main()
{
Console.WriteLine("==========对象排序========");
ArrayList arrObj = new ArrayList();
Person p1 = new Person() {
Name = "hjk",
Age = 100,
Email = "hhh@andyvj.com"
};
Person p2 = new Person() {
Name = "gdss",
Age = 90,
Email = "sd@andyvj.com"
};
Person p3 = new Person() {
Name = "cbv",
Age = 800,
Email = "ge@andyvj.com"
};
Person p4 = new Person() {
Name = "rtsssy",
Age = 70,
Email = "ghkj@andyvj.com"
};
arrObj.Add(p1);
arrObj.Add(p2);
arrObj.Add(p3);
arrObj.Add(p4);
Console.WriteLine("元素个数:" + arrObj.Count);
// ▼ 直接调用Sort()方法是使用person类型实现了IComparab1e接口的默认方式来排序
// arrObj.Sort();
for (int i = 0; i < arrObj.Count; i++) {
Console.WriteLine(((Person)arrObj[i]).Age);
}
// 看 Sort() 函数的重载提示,有 IComparer 接口类型参数,一个比较器。
// 所以有一个实现了接口的类就可以了。
arrObj.Sort(new PersonSortByNameLengthAsc());
Console.WriteLine("==========姓名长短排序后========");
for (int i = 0; i < arrObj.Count; i++) {
Console.WriteLine(((Person)arrObj[i]).Name);
}
}
}
public class Person: IComparable
{
public string Name {
get;
set;
}
public int Age {
get;
set;
}
public string Email {
get;
set;
}
public int CompareTo(object obj)
{
Person p = obj as Person;
if (p != null) {
return this.Age - p.Age;
}
return 0;
}
}
// ▼ 这个类就是一个比较器
public class PersonSortByNameLengthAsc : IComparer
{
public int Compare(object x, object y)
{
Person p1 = x as Person;
Person p2 = y as Person;
if (x != null && y != null) {
return p1.Name.Length - p2.Name.Length;
} else {
throw new Exception("null 无法比较");
}
}
}
// 总结:如果要升序再写一个类实现 IComparer,如果按年龄再写一个类实现IComparer,依次… 有多少个情况
// 就写多少个比较的类就行了,不用去改源代码了。
}
输出:
==========对象排序========
元素个数:4
100
90
800
70
==========姓名长短排序后========
hjk
cbv
gdss
rtsssy
请按任意键继续. . .
参考:
1.C# .Net基础加强第六天 // B站视频教程地址,来自:传智播客