Bootstrap

C#中的Array数组,List集合和ArrayList集合--07

目录

一.Array数组概念的简单理解

1.数组的初始化

2.数组的长度

3.数组的克隆和复制

4.数组的清空

5.数组的查找

6.数组的逆转

7.数组的拓展和缩减

 8.数组的比较

9.数组的合并

10.使用Array类中的静态方法,如Array.Sort,Array.BinarySearch 等

二.Array数组进阶

1.二维数组

2.多维数组

 3.交错数组

4.隐式类型数组

三.List集合

1.基本概念

2.声明和初始化

 3.List集合中的常用方法

四.ArrayList集合

1.基本概念:

2.声明和初始化

3.ArrayList中的常用方法

五.总结

Array(数组)

List

ArrayList

三者之间的异同


一.Array数组概念的简单理解

1.数组的初始化

在C#中,可以在声明数组时同时进行初始化.

数组是一种基本的数据结构,用于存储固定大小的同类型元素集合

创建数组的一般格式:  数组类型[] 数组名称=new数组类型[数组长度]

以下是常见的几种方式

代码示例:

// 一维数组初始化   
int[] numbers = new int[] { 1, 2, 3, 4, 5 };
   
// 简化的语法   
int[] numbers2 = { 1, 2, 3, 4, 5 };
   
// 多维数组初始化   
int[,] matrix = new int[,] { { 1, 2 }, { 3, 4 } };
   
// 交错数组初始化   
int[][] jaggedArray = new int[][]    
{
    new int[] { 1, 2 },
    new int[] { 3, 4, 5 }   
};

在完成数组的创建后 ,可以根据数组的索引进行初始化,赋值,访问等操作

注意:数组的索引从0作为起始,以数组的长度减一作为终止

假设一个数组的长度为5

//假设一个数组的长度为5
//int[] arr = new int[5] { 1, 2, 3, 4, 5 };
int[] arr = { 1, 2, 3, 4, 5 };
//数组元素: 1 2 3 4 5
//数组索引: 0 1 2 3 4
Console.WriteLine(arr.Length); //通过Length属性获取数组的长度
Console.WriteLine(arr[3]); // 输出索引为3的元素(输出4)
arr[3]= 100; //修改数组索引为3的元素为100
//数组元素: 1 2 3 100 5
//数组索引: 0 1 2 3   4
Console.WriteLine(arr[3]);// 输出索引为3的元素(输出100)
//Console.WriteLine(arr[5]);  //索引越界,如果强行进行编译,会报如下错误:
//Unhandled exception. System.IndexOutOfRangeException: Index was outside the bounds of the array.

2.数组的长度

在数组中,Length属性可以获取数组的长度(即数组的元素)

代码示例:

int[] numbers = { 1, 2, 3, 4, 5 };   
int length = numbers.Length; // length = 5

3.数组的克隆和复制

在数组中,可以使用Clone方法和Array.Copy方法来复制数组

代码示例:

int[] original = { 1, 2, 3, 4, 5 };
   
// 使用 Clone 方法   
int[] clone = (int[])original.Clone();
   
// 使用 Array.Copy 方法   
int[] copy = new int[original.Length];   
Array.Copy(original, copy, original.Length);

4.数组的清空

Array.Clear方法可以将数组中所有的元素设置为默认值(比如int类型的默认值是0)

代码示例:

int[] numbers = { 1, 2, 3, 4, 5 };
Array.Clear(numbers, 0, numbers.Length); // 数组中的所有元素将变为0

5.数组的查找

在C#的数组中可以使用Array.IndexOf和Array.Find等方法去查找特定的元素

代码示例:

int[] numbers = { 1, 2, 3, 4, 5 };
   
// 使用 Array.IndexOf   
int index = Array.IndexOf(numbers, 3); // index = 2
   
// 使用 Array.Find
int number = Array.Find(numbers, n => n > 3); // number = 4   

6.数组的逆转

Array.Reverse方法可以翻转数组中的元素顺序

代码示例:

int[] numbers = { 1, 2, 3, 4, 5 };
Array.Reverse(numbers); // numbers = { 5, 4, 3, 2, 1 }   

7.数组的拓展和缩减

在C#中一般来说Array数组的大小是在创建时固定的,一旦定义了数组就不能直接更改.

但是可以去使用Array.Resize方法去调整数组的大小

代码示例:

int[] numbers = { 1, 2, 3, 4, 5 };   
Array.Resize(ref numbers, 3); // numbers = { 1, 2, 3 }
Array.Resize(ref numbers, 7); // numbers = { 1, 2, 3, 0, 0, 0, 0 }   
//需要注意的是当你增加数组大小时,新增加的位置将被初始化为该类型的默认值(对于数值类型是0,对于引用类型是null)。当你减少数组大小时,超出新长度的元素将被丢弃。

 8.数组的比较

为了比较两个数组是否完全相同,可以通过遍历数组元素逐个比较,或者使用SequenceEqual方法来比较两个数组是否相同.

代码示例:

int[] array1 = { 1, 2, 3 };   
int[] array2 = { 1, 2, 3 };

// 使用 SequenceEqual 方法(需要 System.Linq 命名空间)   
bool areEqual = array1.SequenceEqual(array2); // areEqual = true   

9.数组的合并

在C#中,我们可以去使用Concat方法去合并两个数组\

代码示例:

int[] array1 = { 1, 2, 3 };   
int[] array2 = { 4, 5, 6 };

// 使用 Concat 方法(需要 System.Linq 命名空间)
int[] merged = array1.Concat(array2).ToArray(); // merged = { 1, 2, 3, 4, 5, 6 }   

10.使用Array类中的静态方法,如Array.Sort,Array.BinarySearch 等

代码示例:

int[] numbers = { 3, 1, 4, 5, 2 };
   
// 使用 Array.Sort 方法进行排序
Array.Sort(numbers); // numbers = { 1, 2, 3, 4, 5 }

// 使用 Array.BinarySearch 方法进行二分查找(前提是数组已排序)
int index = Array.BinarySearch(numbers, 4); // index = 3

二.Array数组进阶

1.二维数组

二维数组可以看作是数组的数组,即每个元素都是一个数组.例如,一个2行3列的二维数组可以看作是一个包含2个数组的数组,每个数组包含3个元素

二维数组也能够将其理解为多维数组的一种特殊形式,可以看做一个矩阵或者表格,具有行和列

// 声明一个二维数组   
int[,] matrix = new int[2, 3]; // 2行3列
   
// 初始化一个二维数组   
int[,] initializedMatrix = new int[,]   
{
    { 1, 2, 3 },
    { 4, 5, 6 }
};
   
// 访问二维数组的元素   
int element = initializedMatrix[1, 2]; // 获取第二行第三列的元素,值为6

二维数组的特点:

  • 二维数组是以矩阵形式存储的
  • 元素通过两个索引访问,第一个索引表示行,第二个索引表示列
  • 在内存中是以行优先顺序存储的

2.多维数组

多维数组通常指代维度大于二的数组,可以用于表示更加复杂的数据结构

下面使用三维数组来举例

// 声明一个三维数组   
int[,,] threeDimensional = new int[2, 3, 4]; // 2个2D数组,每个3行4列
   
// 初始化一个三维数组   
int[,,] initializedThreeDimensional = new int[,,]   
{
    {
        { 1, 2, 3, 4 },
        { 5, 6, 7, 8 },
        { 9, 10, 11, 12 }
    },
    {
        { 13, 14, 15, 16 },
        { 17, 18, 19, 20 },
        { 21, 22, 23, 24 }
    }   
};
   
// 访问三维数组的元素   
int element = initializedThreeDimensional[1, 2, 3]; // 获取第二个2D数组第三行第四列的元素,值为24

多维数组的特点:

  • 支持多个维度,每个维度可以有不同的大小
  • 通过多个索引访问元素,每个索引对应一个维度。

 3.交错数组

交错数组(或锯齿数组)是数组的数组,其中每个子数组的长度可以不同.

代码示例:

// 声明一个交错数组   
int[][] jaggedArray = new int[3][]; // 3个子数组
   
// 为每个子数组分配不同的长度   
jaggedArray[0] = new int[2]; // 第一个子数组有2个元素   
jaggedArray[1] = new int[3]; // 第二个子数组有3个元素   
jaggedArray[2] = new int[4]; // 第三个子数组有4个元素
   
// 初始化交错数组   
int[][] initializedJaggedArray = new int[][]   
{
    new int[] { 1, 2 },
    new int[] { 3, 4, 5 },
    new int[] { 6, 7, 8, 9 }   
};
   
// 访问交错数组的元素   
int element = initializedJaggedArray[1][2]; // 获取第二个子数组的第三个元素,值为5

交错数组的特点:

  • 每个子数组可以有不同的长度
  • 在内存中,子数组是独立的数组,可以分布在不同的位置

4.隐式类型数组

隐式类型化数组利用C#的类型推断功能,由编译器根据数组的初始值推断数组的类型.

代码示例:

// 使用隐式类型化数组   
var numbers = new[] { 1, 2, 3, 4, 5 };
   
// 编译器推断出 numbers 是一个 int[] 类型的数组
   
// 对于复杂类型   
var complexArray = new[]   
{
    new { Name = "Alice", Age = 30 },
    new { Name = "Bob", Age = 25 }
};

// 编译器推断出 complexArray 是一个匿名类型数组

隐式类型数组的特点:

  • 编译器根据初始值推断数组的类型,要求所有初始值的类型必须兼容
  • 可以提高代码的可读性,尤其是在复杂类型的情况下

三.List集合

在C#中,List<T>是一个非常常用的泛型集合,它提供了动态数组的功能.与普通数组相比,List<T>具有更灵活的大小调整能力,并且提供了许多方便的方法来操作集合中的元素.以下是关于List<T>的详细信息:

1.基本概念

  • 动态大小:List<T>可以根据需要动态调整其大小.你可以添加或移除元素,而不需要手动管理内存.
  • 泛型支持:List<T>是一个泛型集合,这意味着你可以指定元素的类型,这提供了类型安全性和性能优化.

2.声明和初始化

代码示例:

// 声明一个 List<int>   
List<int> numbers = new List<int>();
   
// 初始化一个 List<string> 并添加元素   
List<string> names = new List<string> { "Alice", "Bob", "Charlie" };

 3.List集合中的常用方法

  1. 添加元素
    numbers.Add(10); // 添加单个元素
    numbers.AddRange(new int[] { 20, 30, 40 }); // 添加多个元素
    
  2. 插入元素
    numbers.Insert(1, 15); // 在索引1处插入元素15
    
  3. 删除元素
    numbers.Remove(10); // 移除值为10的元素
    numbers.RemoveAt(0); // 移除索引0处的元素
    numbers.RemoveRange(0, 2); // 移除从索引0开始的两个元素
    
  4. 访问元素
    int firstNumber = numbers[0]; // 访问第一个元素
    
  5. 查找元素
    int index = numbers.IndexOf(30); // 查找值为30的元素的索引
    bool contains = numbers.Contains(20); // 检查是否包含值为20的元素
    
  6. 排序
    numbers.Sort(); // 对列表进行升序排序
    numbers.Reverse(); // 反转列表顺序
    
  7. 清空列表
    numbers.Clear(); // 移除所有元素
    

List泛型集合的特点:

  • 自动扩容:List<T>内部实现为一个数组,当需要增加容量时,会自动创建一个更大的数组,并将旧数组中的元素复制到新数组中.这个过程可能会影响性能,尤其是在频繁添加大量元素时
  • 索引访问:与数组类似,List<T>支持通过索引访问元素,访问速度很快
  • 线程安全:List<T>不是线程安全的.在多线程环境中使用时,需要手动实现同步

List集合的应用场景 :

  • 频繁更改大小的集合:List<T>非常适合需要频繁添加,删除或调整大小的集合
  • 需要类型安全的集合:由于List<T>是泛型的,它可以确保集合中的所有元素都是同一类型

四.ArrayList集合

ArrayList集合:

ArrayList是 C# 中一种非泛型集合类,用于存储元素列表.它在 .NET Framework 1.0 引入,适用于早期不支持泛型的场景.尽管在现代开发中推荐使用泛型集合如List<T>,但了解 ArrayList仍然有助于理解 C# 集合的演变和处理非泛型数据的方式

1.基本概念:

  • 非泛型:ArrayList可以存储任何类型的对象,因为它存储的是object类型.这意味着你可以在同一个 ArrayList中存储不同类型的数据
  • 动态大小:与List<T>类似,ArrayList可以根据需要自动调整其大小。

2.声明和初始化

代码示例:

// 声明一个 ArrayList   
ArrayList arrayList = new ArrayList();
   
// 初始化并添加元素   
ArrayList mixedList = new ArrayList() { 1, "hello", 3.14, true };

3.ArrayList中的常用方法

  1. 添加元素
    arrayList.Add(10); // 添加单个元素
    arrayList.AddRange(new object[] { "world", 20.5 }); // 添加多个元素
    
  2. 插入元素
    arrayList.Insert(1, "inserted"); // 在索引1处插入元素
    
  3. 删除元素
    arrayList.Remove(10); // 移除指定值的元素
    arrayList.RemoveAt(0); // 移除索引0处的元素
    arrayList.RemoveRange(0, 2); // 移除从索引0开始的两个元素
    
  4. 访问元素
    var firstElement = arrayList[0]; // 访问第一个元素
    
  5. 查找元素
    int index = arrayList.IndexOf("hello"); // 查找元素的索引
    bool contains = arrayList.Contains(3.14); // 检查是否包含某个元素
    
  6. 排序
    arrayList.Sort(); // 对列表进行排序
    
  7. 清空列表
    arrayList.Clear(); // 移除所有元素
    

性能和使用注意:

  • 装箱和拆箱:由于ArrayList存储的是object类型,对于值类型(如int和double),会发生装箱和拆箱操作,可能影响性能
  • 类型安全性:ArrayList不提供编译时类型检查,可能导致运行时错误.例如,尝试将不兼容的类型转换为特定类型时
  • 线程安全:ArrayList不是线程安全的.在多线程环境中使用时,需要手动实现同步

应用场景:

  • 早期代码:在泛型引入之前的旧代码中经常使用ArrayList
  • 需要存储不同类型的集合:在某些情况下,可能需要在同一集合中存储不同类型的对象

五.总结

Array(数组)

特点

固定大小:数组一旦创建,其大小是固定的,不能动态调整。

类型安全:数组是强类型的,定义时需要指定元素类型,所有元素必须是同一类型。

高效访问:由于数组在内存中是连续存储的,访问速度非常快。

优点

性能高:由于连续内存分配和类型安全,数组的访问和遍历速度较快。

简单直接:适合用于已知大小和类型的集合。

缺点

大小固定:不能动态调整大小,需要预先定义。

功能有限:没有提供丰富的集合操作方法。

用法:

int[] numbers = new int[5]; // 创建一个长度为5的整数数组   
numbers[0] = 10; // 设置元素   
int first = numbers[0]; // 访问元素

List<T>

特点

动态大小:List<T>可以根据需要动态调整大小。

泛型支持:提供类型安全,所有元素必须是同一类型。

丰富的方法:提供了许多用于操作集合的内置方法,如添加、插入、删除、排序等。

优点

灵活性高:能够处理动态变化的集合大小。

类型安全:通过泛型提供编译时类型检查。

缺点

性能开销:在需要扩容时,会有一定的性能开销,因为需要分配新数组并复制元素。

用法:

List<int> numbers = new List<int>();   
numbers.Add(10); // 添加元素   
int first = numbers[0]; // 访问元素

ArrayList

特点

动态大小:ArrayList也可以根据需要动态调整大小。

非泛型:可以存储不同类型的对象,因为它存储的是object类型。

较旧的集合类型:在 .NET 1.0 时代引入,在泛型出现之前广泛使用。

优点

灵活性高:可以存储不同类型的对象。

动态调整大小:能够处理动态变化的集合大小。

缺点

类型不安全:没有编译时类型检查,可能导致运行时错误。

性能问题:由于装箱和拆箱操作,性能可能较低。

用法:

ArrayList arrayList = new ArrayList();   
arrayList.Add(10); // 添加元素   
arrayList.Add("string"); // 添加不同类型的元素   
object first = arrayList[0]; // 访问元素

三者之间的异同

  • 类型安全性:Array和List<T>提供类型安全,而ArrayList不提供。
  • 大小调整:Array大小固定,List<T>和 ArrayList大小可动态调整。
  • 性能:Array通常性能最好,List<T>次之,ArrayList由于装箱和拆箱可能性能最差。
  • 使用场景:Array适合固定大小的集合,List<T>适合动态大小且类型一致的集合,ArrayList适合需要存储不同类型对象的旧代码。
;