C#重要集合类:列表、字典、队列、栈

主要内容:

重要集合类:列表、字典、队列、栈

  1. Timer定时器,Thread线程)
  2. 集合类:ArrayList、List列表、
  3. 集合类:Dictionary字典、
  4. 集合类:Queue队列、Stack栈

Timer定时器

Timer定时器:每间隔一段时间执行相同的业务逻辑,类似于循环。

定时器在C#中有两种:

  1. 线程安全的定时器

  2. 定时器控件(类)

public sealed class Timer : MarshalByRefObject, IDisposable//定时器是一个密封类。
{
    ...
    public Timer(TimerCallback callback, object state, int dueTime, int period)
    {
        ...
    }
    ...
}


//回调函数

using System.Runtime.InteropServices;

namespace System.Threading;

[ComVisible(true)]
[__DynamicallyInvokable]
public delegate void TimerCallback(object state); //委托
#if false // 反编译日志
缓存中的 9 项
#endif



static void Main(string[] args)
{
//System.Threading.Timer定时器对象,线程安全的定时器对象。定时器能在间隔一段时间后循环调用某个回调函数。
//参数1:回调函数。参数2:向回调函数中传递的参数。定时器启动回头调用的方法。
//参数3:调用回调函数延迟的时间,单位:毫秒,0不迟,立即执行。
//参数4:每间隔多少毫秒执行一次回调函数。1000毫秒=1秒
//System.Threading.Timer timer = new System.Threading.Timer(new TimerCallback(TimerProc), null, 0, 1000) 
    	System.Threading.Timer timer = new System.Threading.Timer(TimerProc, null, 0, 1000); //一个方法如果满足委托,直接写成方法名就行。
        string input = Console.ReadLine(); //在主线程上执行等待用户的输入,不影响打印时间的运行。
        Console.ReadKey();
    
}
    

//方法满足委托:1. 方法返回值和委托返回值类型一致  2.方法参数个数、类型、顺序和委托一样
static void TimerProc(object abc) //分线程,线程安全的定时器
{
    
    Console.Clear();
    //string input = Console.ReadLine(); //阻塞
    Console.WriteLine(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"));
    
}


//另一种Timer的实现方法
static void Main(string[] args)
{
    Console.Title = "时钟";
	Console.ForegroundColor = ConsoleColor.Red;
    
    //写在主线程里,不安全的定时器,在控制台里面不会阻塞主线程,在winform里会阻塞。  定时器实例化
	System.Timers.Timer timer = new System.Timers.Timer(); 
    timer.Interval = 1000; //等待的时间,单位:毫秒,默认100毫秒,double类型
    timer.Elapsed += Timer_Elapsed; //事件:被动触发的,语言程序执行的逻辑。闪电图标,委托皮包。
	
    //定时器启动
	timer.Start();
    string input = Console.ReadLine();
    if(input == 1)
    {
         Console.WriteLine("--------------"); //打印不出来,线程阻塞了。
    }
    
    Console.ReadKey();
}

//sender发送者,谁触发了事件(目标),事件句柄
private static void Timer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
{
     Console.Clear();
     Console.WriteLine("选择功能项:【1】暂停【2】启动");
     
     Console.WriteLine(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"));
}

//运行
static void Main(string[] args)
{
     Console.WriteLine("选择功能项:【1】暂停【2】启动");
     string input = Console.ReadLine();
	if(input == 1)
	{
     	Console.WriteLine("--------------"); 
	}
    else
    {
         System.Timers.Timer timer = new System.Timers.Timer(); 
		timer.Interval = 1000; 
		timer.Elapsed += Timer_Elapsed; 
        
		timer.Start();
    }
		Console.ReadKey();
}

private static void Timer_Elapsed(object sender, System.Timers.ElapsedEvenArgs e)
{
      Console.Clear();
      Console.WriteLine(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"));
 }

Thread线程

  
  static void Main(string[] args)
 {
     Console.Title = "电子时钟";  //设置窗口标题和长度
     // Thread线程,线程在运行比较复杂的任务时,不会阻塞主线程的执行。
     Thread timeThread = new Thread(new ThreadStart(Process)); 
     timeThread.Start();

 	Console.ReadKey(true);
 	timeThread.Abort();  // 线程中止
  }

 //处理线程
 static void Process()
 {
     // 死循环
     while (true)
     {
         Console.Clear();
         Console.WriteLine(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")); 
         Thread.Sleep(1000);  // 线程睡1秒,延迟1秒
     }
 }

分线程里死循环用的比较多,不影响主线程。

任务Task管理线程比Thread更灵活一点。

数组ArrayList

数组和集合概念,以及它们的区别:

  • 数组【一般是相同数据类型】(object[]数组元素类型可以不同)的元素按一定顺序排列的集合。
  • 数组在添加,插入,删除不方便。说明数组不是链表。
  • 数组是集合,集合不一定是数组。Collection
  • 数组读取(查询)速度比集合快。集合是线性表,在插入,添加,删除数据时比较方便,性能比数组会高。
  • 数组存储的类型不限制。集合存储的类型只能是引用类型。

C#中的集合(Collection)和数组(Array)是两种不同的数据结构,它们之间有以下主要区别:

  1. 定义方式不同:集合是使用集合类定义的,如List或HashSet。数组是使用类型和大小显式定义的。
  2. 大小不同:数组的大小在创建后无法更改,而集合的大小可以根据需要动态增长。
  3. 内存布局不同:数组在内存中是连续的,而集合通常不是。
  4. 性能不同:访问数组元素通常比访问集合元素快,因为集合元素访问时可能需要进行装箱和拆箱操作。
  5. 索引访问:数组可以通过索引直接访问元素,而集合则需要使用迭代器或者在.NET 2.0及以上版本中使用foreach循环。
  6. 数据类型不同:数组可以存储基本数据类型(值类型),也可以存储引用类型,【而集合只能存储引用类型】,因为它们都继承自System.Object。

static void Main(string[] args)
{

	//public class ArrayList : IList, ICollection, IEnumerable, ICloneable
	//Iist列表 ICollection集合,IEnumerable可枚举,可迭代,可循环,ICloneable 可克隆,可复制
    ArrayList arrayList1 = new ArrayList(); // 没有指定容量(常用)
	ArrayList arrayList2 = new ArrayList(3); // 指定容量,提醒:没有存储任何的项,Count还是0
	ArrayList arrayList3 = new ArrayList(new int[] { 1, 2, 3 });// 放一个实现ICollection接口的集合

	// 1。添加,注意装箱,支持多种数据类型,取值时要拆箱,
	arrayList1.Add(1);
	arrayList1.Add("abc");
	arrayList1.Add(true);
	// Rang范围,一次添加多个
	arrayList1.AddRange(new object[] { "hello", false, 20, 10, 20, 30, 40, 50, 60, 70, 80 });
	arrayList1.AddRange(new List<int> { 1, 2, 3 });
	arrayList1.AddRange(new Dictionary<string, string>() {
    { "key1","value1"},
    { "key2", "value2" }
});

	// 2。清空
    //arrayList1.Clear();

    // 3。删除一个
    //arrayList1.Remove("abc");  // 按值删除
    //arrayList1.RemoveAt(0);  // 按索引删除,有可能索引越界
    //arrayList1.RemoveRange(0, 2);

    // 4。取值
    Console.WriteLine(arrayList1[0]);
    Console.WriteLine(arrayList1[1]);
    Console.WriteLine(arrayList1[2]);

    KeyValuePair<string, string> keyValuePair = (KeyValuePair<string, string>)arrayList1[arrayList1.Count - 1];
    Console.WriteLine($"key:{keyValuePair.Key},value:{keyValuePair.Value}");

    Console.WriteLine("----------------");
    //Console.WriteLine(arrayList2[1]);  // 只有容量,没有存储项,索引越界

    // 5。取数量
    Console.WriteLine($"容量:{arrayList1.Capacity},数量:{arrayList1.Count}");  // Array.Length,集合的长度,集合中项的个数
    Console.WriteLine(arrayList2.Count);
    Console.WriteLine(arrayList3.Count);

    // 6。如下属性和方法了解:
    Console.WriteLine(arrayList1.IsReadOnly);// 是否只读
    Console.WriteLine(arrayList1.IsFixedSize);// 是否固定大小,
    ArrayList newArrayList = ArrayList.FixedSize(arrayList2); // FixedSize()固定大小
    Console.WriteLine(newArrayList.IsFixedSize);// 是否固定大小,
    Console.WriteLine(arrayList1.IsSynchronized);// 是否同步(少用)

    // 7。取容量
    // Capacity != Count,Capacity 是 可以存储的元素 ArrayList 数。 Count 是 中实际 ArrayList包含的元素数。
    // Capacity 始终大于或等于 Count。 结论:Add和AddRange在给ArrayList扩容的机制不太一样。
    // Add()扩容机制:2的次冥
    Console.WriteLine(arrayList2.Capacity);
    Console.WriteLine(arrayList3.Capacity);

    // 8。复制(了解)
    // 浅复制,装箱的操作,复制的源(原始的)和复制对象(新的)之间不会相互影响。
    ArrayList arr1 = (ArrayList)arrayList1.Clone();
    // ArrayList arr1 = arrayList1;  // 会相互影响。
    arrayList1.Add(20);
    arr1.Add(40);
    Console.WriteLine(arr1[arr1.Count - 1]);
    Console.WriteLine(arrayList1[arrayList1.Count - 1]);

    // 9。判断是否包含某项  返回布尔值
    Console.WriteLine(arrayList1.Contains(200));


    // 10。查索引,和string查索引一样规律。
    Console.WriteLine(arrayList1.IndexOf(1));  // 0
    Console.WriteLine(arrayList1.IndexOf("abc")); // 1
    Console.WriteLine(arrayList1.IndexOf(200));  // -1

    Console.WriteLine(arrayList1.LastIndexOf(1));  // 0
    Console.WriteLine(arrayList1.LastIndexOf("abc")); // 1
    Console.WriteLine(arrayList1.LastIndexOf(200));  // -1

    // 11。插入
    arrayList1.Insert(0, 2);  // 在某个索引前插入一项
    arrayList1.InsertRange(0, new char[] { 'a', 'b' });
    Console.WriteLine(arrayList1[0]);

    // this[]
    // IEnumerator enumerator= arrayList1.GetEnumerator();
    // enumerator.MoveNext();

    Console.WriteLine("----------------------------------------");

    // 12。循环, for,while,foreach, Array.ForEach()
    /*Array.ForEach(arrayList1.ToArray(), (item) => {
        Console.WriteLine(item);
    });*/

    foreach (var item in arrayList1)
    {
        Console.WriteLine(item);
    }

    // 13。集合查询,需要借助数组 
    // ToArray()转成数组
    object[] obj2 = Array.FindAll(arrayList1.ToArray(), (item) =>
     {
         bool flag = IsNumeric(item.ToString());
         if (flag)
         {
             int num = int.Parse(item.ToString());
             if (num >= 10 && num <= 50)
             {
                 return true;
             }
         }
         return false;
     });
    ArrayList arr3 = new ArrayList(obj2);  // 把数组再转换成ArrayList

    // 14。反转和排序
    //arrayList1.Reverse();  // 反转集合中项的顺序,会影响原集合
    //arrayList1.Sort();

    List<int> ints = new List<int>() { 10,20,30};
    ArrayList.Adapter(ints);  // 适配器:把实现IList接口的其他对象转换成ArrayList

    Console.ReadKey();
}


	public static bool IsNumeric(string str)
{
    Regex regex = new Regex("^[0-9]+$");
    return regex.IsMatch(str);
}

列表List

  • 列表List对象,也是集合,并且是最流行的集合。
  • List列表中的数据类型是统一的。
  • List整体是一个类型,由泛型和列表组成的复合类型,也称泛型列表。List也是类型,int也是类型,表示未知类型。
  • 泛型就是让这个列表支持多种类型。
  • 泛型列表和ArrayList集合最大区别:List列表中的项类型是统一的,而ArrayList集合中的项类型可以不同。

// 比较器前提:实现
public class ListCompare : IComparer<Student>
{
    public int Compare(Student x, Student y)
    {
        /* if (x.Id == y.Id)
         {
             return 0;
         }
         else
         {
             if (x.Id > y.Id)
             {
                 return -1;
             }
             else
             {
                 return 1;
             }
         }*/
    	return x.Name.CompareTo(y.Name);
	}
}

  
  public class Student
 {
     public int Id { get; set; }
     public string Name { get; set; }
     public int Age { get; set; }
 	 public override string ToString()
 	{
     	return $"编号:{Id},名称:{Name}";
 	}
 }
 
static void Main(string[] args)

{

    // 列表List对象,也是集合,并且是最流行集合

    // List列表中的数据类型是统一的

    // List<int>整体是一个类型,复合类型,List也是类型,int也是类型  <T>表示未知类型

    // 也称泛型列表。和ArrayList集合最大区别:List列表中的项类型是统一的,而ArrayList集合中的项类型可以不同。

    List<int> list1 = new List<int>() { 1,1,1};

    List<string> list2 = new List<string>() { "abc" };

Student one = new Student() { Id = 1, Name = "张三1" };
List<Student> student1 = new List<Student>() {
    one,
    new Student(){ Id=2,Name="张三1"},
    new Student(){ Id=3,Name="张三2"},
};

// 查询, 修改:(增,删,插)

// 1。查询数据:FindAll()正向查多项,Find()正向查一项,FindLast()倒查一项
List<Student> stus = student1.FindAll(stu => stu.Name == "张三1");
Student stu1 = student1.Find(stu => stu.Name == "张三1");
Student stu2 = student1.FindLast(stu => stu.Name == "张三1");
Console.WriteLine(stu1.Id);
Console.WriteLine(stu2.Id);
Console.WriteLine("--------------------------------");

// 2。查索引  IndexOf(), LastIndexOf(), FindIndex(), FindLastIndex()
int index1 = student1.IndexOf(one);//0
int index2 = student1.IndexOf(new Student() { Id = 1, Name = "张三1" });//-1
int index3 = student1.FindIndex(stu => stu.Id == 2);

Console.WriteLine(index1);  // 0
Console.WriteLine(index2);  // -1
Console.WriteLine(index3); // 1

// 3。添加
student1.Add(new Student() { Id = 3, Name = "李四" });
student1.AddRange(
 new Student[]
{
    new Student(){ Id = 4, Name = "李四1"},
    new Student(){ Id = 5, Name = "李四2"},
});

student1.Sort(new ListCompare());

student1.ForEach(student =>
{
    Console.WriteLine(student);
});

Console.WriteLine("--------------------");

foreach (var item in student1)
{
    Console.WriteLine(item);
}

List<object> strList = student1.ConvertAll<object>((stu) =>
{
    return new { Name = stu.Name, Age = stu.Age };
});

//student1.Clear();// 清空,没有任何条件
//student1.RemoveAll(stu => stu.Id < 2); // 满足条件删除

student1.InsertRange(0, new Student[] {
    new Student(){ Id = 6, Name = "王五1"},
    new Student(){ Id = 7, Name = "王五2"},
});

Dictionary<string, string> dict = new Dictionary<string, string>() {
    { "key1", "value1"},
    { "key2", "value2"},
};

dict.Add("key3", "value3"); // key不能重复

// KeyValuePair<string,string>可以var替代
foreach (KeyValuePair<string,string> item in dict)
{
    // item是一个键值对
    Console.WriteLine($"{item.Key}, {item.Value}");
}

// 想保存在线用户,Array,ArrayList,List,Dictionary
Console.WriteLine("----------------");
var keys = dict.Keys;   // Keys是所有的键组成的集合。Values所有的值组成的集合。
foreach (var item in keys)
{
    Console.WriteLine(item);
}

Queue queue = new Queue();
queue.Enqueue(1);
queue.Enqueue("你好");
queue.Enqueue(true);
queue.Enqueue(6.5);

Console.WriteLine(queue.Count);
object obj =  queue.Dequeue();
Console.WriteLine(obj);
Console.WriteLine(queue.Count);

foreach (var item in queue)
{
    Console.WriteLine(item);
}

HashSet<int> hs = new HashSet<int>() { 1, 2, 3,1 };

Console.ReadKey();
}

重要接口:
public abstract class Array : ICloneable, IList, ICollection, IEnumerable, IStructuralComparable, IStructuralEquatable

数组实现了6个接口,前4个接口很重要

  1. ICloneable接口控制克隆,复制对象
  2. IList列表接口,控制对象操作(添加,删除等)
  3. IEnumerable可枚举对象的接口,控制是对象的循环
  4. ICollection集合接口,控制复制对象
  • public interface IList : ICollection, IEnumerable 说明列表也是集合的一种。

  • public class ArrayList : IList, ICollection, IEnumerable, ICloneable

  • public class List : IList, ICollection, IEnumerable, IEnumerable, IList, ICollection, IReadOnlyList, IReadOnlyCollection

集合和列表的对比:
在C#中,List和HashSet都是集合类。
List是一个有序集合,可以通过索引访问元素。元素可以重复。
HashSet是一个无序集合,不能通过索引访问元素。元素不可以重复。

数组,列表都是集合。
数组不支持泛型,数组元素数据类型可以相同,也可不相同。而列表支持泛型,元素数据类型相同。
数组元素有序,列表元素也有序。
集合中元素可以有序,也可以无序。

迭代器,生成器(索引器):

迭代器:一个对象能循环,靠的是对象拥有迭代器。
谁来创造(生成)迭代器,生成器(索引器)来生成迭代器。
C#中生成器,叫成索引器。

posted @ 2024-07-30 20:41  海域  阅读(28)  评论(0编辑  收藏  举报