首页 > 编程语言 >C#重要集合类:列表、字典、队列、栈

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

时间:2024-07-30 20:39:23浏览次数:10  
标签:Console C# List 队列 arrayList1 WriteLine 集合 new 字典

主要内容:

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

  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#中生成器,叫成索引器。

标签:Console,C#,List,队列,arrayList1,WriteLine,集合,new,字典
From: https://www.cnblogs.com/dbsdb/p/18333326

相关文章

  • Docker-harbor私有仓库部署
    目录什么是Harbor?Harbor的介绍Harbor的特性Harbor的构成Harbor部署实验一、部署Docker-Compose服务二、部署Harbor服务(一)在/opt上传harbor压缩包(二)修改harbor安装的配置文件(三)启动Harbor三、查看Harbor启动镜像四、登录验证什么是Harbor?Harbor的介绍Harbor是......
  • 理解 C# 中的索引器(Indexer)详解与示例
    文章目录1.索引器的基本概念2.索引器的语法3、索引器示例3.1.定义一个简单的索引器3.2.使用索引器4、索引器进阶4.1.多维索引器4.2.索引器重载5.索引器的注意事项6.总结在C#中,索引器(Indexer)是一种特殊的属性,允许类的实例像数组一样通过索引访问。索引器......
  • TCP为什么需要四次挥手?
    tcp为什么需要四次挥手?答案有两个:1.将发送fin包的权限交给被动断开方的应用层去处理,也就是让程序员处理2.接第一个答案,应用层有了发送fin的权限,可以在发送fin前继续向对端发送消息为了搞清楚这个问题,我们先要了解四次挥手的过程:1.注意事项tcp四次挥手过程中没有客户......
  • 7 .30 ACM总结
    放假前几天,老师让我们打一场ACM来放松一下(非常好,放松不一定,被压力了)C题C题是个非常水的搜索题,队友看一眼就秒了。写的时候出了一点小问题,但也调出来了,此时我们来到了第6(总共7队)。#include<bits/stdc++.h>#definelllonglongusingnamespacestd;constintN=1e3+5;......
  • CF538H Summer Dichotomy 题解
    Description有\(T\)名学生,你要从中选出至少\(t\)人,并将选出的人分成两组,可以有某一组是空的。有\(n\)名老师,每名老师要被分配到两个小组之一,对于第\(i\)名老师,要求所在的小组中的学生人数\(\in[l_i,r_i]\)。此外,有\(m\)对老师不能在同一个小组中。你需要判断能否......
  • Android开发 - List类中的CopyOnWriteArrayList实现类解析
    CopyOnWriteArrayList是什么CopyOnWriteArrayList是Java并发包(java.util.concurrent)中的一个并发安全的List实现类。它具有特定的设计,使得在并发场景下,读操作(如迭代)可以并发进行,而写操作(如添加、修改、删除)会进行一定的同步,但不会阻塞读操作主要特点和用法:线程安全......
  • python高性能计算:cython入门代码
    三种实现的对比:(1)纯pythonx.pydefis_prime(num):forjinrange(2,num):if(num%j)==0:returnFalsereturnTrueimporttimea=time.time()foriinrange(10,100000):is_prime(i)b=time.time()print(b-a)(2)x2.py......
  • SP8099 TABLE - Crash´s number table 题解
    题目传送门前置知识一般的积性函数|数论分块|莫比乌斯反演解法令\(n\lem\)。考虑莫比乌斯反演,推式子,有\(\begin{aligned}&\sum\limits_{i=1}^{n}\sum\limits_{j=1}^{n}\operatorname{lcm}(i,j)\\&=\sum\limits_{i=1}^{n}\sum\limits_{j=1}^{n}\frac{ij}{\gcd(i,j)......
  • 《NET CLR via C#》---第三章("运行时"解析类型引用)
    "运行时"解析类型引用首先在"C:\Users\LH89\source\repos"目录下,新建Console1工程(C#控制台)实现简单的代码,并编译为程序集(假定名为Program.exe)usingSystem;publicclassProgram{staticvoidMain(string[]args){Console.WriteLine("HelloWorld"......
  • c语言笔记(2024.7.24)第三天
    常量与变量概念:·表面:程序运行过程中取值可以改变的数据·实际:变量其实代表了一块内存区域/单元/空间。变量名可视为该区域的标识。整个变量分为三部分:·变量名:这个只是变量的一个标识,我们借助变量名来存取数据。·变量空间/存储单元:这个就是内存中分配的一块用来存放......