C# 数组

如果需要使用同一类型的多个对象,可使用集合和数组。C#用特殊的记号声明、初始化、使用数组。如果需要使用不同类型的多个对象,可使用元组(Tuple)类型。

利用数组声明可在单个变量中存储同一种类型的多个数据项,可利用索引来单独访问数据项。C#的数组索引是从0开始的,也就是说C#中的数组是基于0的。

#region 一维数组
//数组定义:数据类型[] 数组名 = new 数据类型[数组长度];
int[] arr = new int[3];
//数组赋值
arr[0] = 1;
arr[1] = 2;
arr[2] = 3;
//数组遍历
for(int i=0; i<arr.Length; i++)
{
    Console.WriteLine(arr[i]);
}
#endregion

虽然C#变成经常使用数组,但目前在存储数据集合时,大多数程序使用的都是泛型集合类型而不是数组。

数组声明
声明数组时应先定义数组中元素的类型

//声明一维数组
string[] arr;

//声明二维数组
int[,] cells;

数组初始化

  • 声明数组后必须为数组分配内存,以保存数组的元素。
  • 数组是引用类型,必须给它分配堆上的内存。
  • 数组使用new运算符指定数组中元素的类型和数量来初始化数组的变量
int[] arr;
arr = new int[3];

数组声明并初始化

int[] arr = new int[3];

数组声明初始化并赋值

int[] arr = new int[3]{1,2,3};

数组实例化

C#3.0起不必在new后指定数组的数据类型,编译器能根据初始化列表中的数据类型推断出数组元素的类型。

//声明数组并实例化
string[] languages = { "C", "C++", "C#" };

#region 一维数组
//数组定义并赋值
int[] arr = { 1, 2, 3, 4, 5, 6, 7 }; 
//数组遍历
for(int i=0; i<arr.Length; i++)
{
    Console.WriteLine(arr[i]);
}
#endregion

数组声明后再赋值

//若在声明后赋值则需使用new关键字
string[] languages;
languages = new string[] { "C", "C++", "C#" };

数组声明时使用new进行赋值

string[] languages = new string[] { "C", "C++", "C#" };

使用new关键字会让“运行时”为数据类型分配内存,new指示“运行时”实例化数据类型。

使用new关键字可指定数组大小

string[] languages = new string[3]{"C","C++","C#"};

分配数组但不指定初始值

string[] languages = new string[3];

分配数组但不制定初始值仍会初始化每个元素,运行时将每个云素初始化为默认值。

  • 引用类型初始化为null
  • 数值类型初始化为0
  • 布尔类型初始化为false
  • 字符类型初始化为\0

运行时定义数组大小

string[] languages;
Console.Write("How many items on the list?");
int size = int.Parse(Console.ReadLine());
languages = new string[size];

声明数组并访问

string[] languages = new string[3] { "C", "C++", "C#" };
string language = languages[languages.Length];

数组的长度是固定的,不能随便更改,除非重新创建数组。
数组越界会造成运行时错误

数组排序

string[] arr = new string[] { "Java", "C++", "Lua" };
Array.Sort(arr);
for(int i=0; i<arr.Length; i++)
{
    Console.WriteLine(arr[i]);
}
Console.ReadLine();

查询数据元素返回索引

string[] arr = new string[] { "C", "Java", "Swift" };
int index = Array.BinarySearch(arr, "java");
Console.WriteLine(index);//-2
Console.ReadLine();

数组反转

string[] arr = new string[] { "java", "c", "php" };
Array.Reverse(arr);
for(int i=0; i<arr.Length; i++)
{
    Console.WriteLine(arr[i]);
}
Console.ReadLine();

数组置空

string[] arr = new string[] { "html", "css", "javascript" };
Array.Clear(arr, 0, arr.Length);
for(int i=0;i<arr.Length; i++)
{
    Console.WriteLine(arr[i]);
}
Console.ReadLine();
  • Clear()不能删除数组元素且不能将长度设置为0,数组大小是固定的,不能修改。
  • Clear()是将数组中的每个元素都设置为默认值

回文

回文指的是正反读都一样的句子,例如NeverOddOrEven。

Console.Write("enter a palindrome: ");
string palindrome = Console.ReadLine();

string str = palindrome.Replace(" ", "");//剔除空格
str = str.ToLower();//字母转小写
char[] arr = str.ToCharArray(); //将字符串转换为字符数组
Array.Reverse(arr);  //反转数组元素
string result = new string(arr);

Console.WriteLine(result == palindrome ? "YES" : "NO");
Console.ReadLine();

数组使用引用类型

namespace TestApp
{
    public class User
    {
        //自动实现的属性
        public string UserName { get; set; }
        public string Password { get; set; }
        //重写Object类的ToString()
        public override string ToString() => $"{UserName} {Password}";
    }
    class Program
    {
        static void Main(string[] args)
        {
            //声明包含类元素的数组
            User[] arr = new User[2];
            //数组元素若是引用类型,就必须为每个数组元素分配内存。
            //若使用数组中未分配内存的元素会抛出NullReferenceException类型的异常

            //为数组元素分配内存
            arr[0] = new User { UserName = "Admin", Password = "1syhljt@2018" };
            arr[1] = new User { UserName = "SA", Password = "2zhllcl@2018" };
        }
    }
}

链表

Random rd = new Random();       

var list = new List<int>();
list.Add(rd.Next(100000, 999999));
list.Add(rd.Next(100000, 999999));
list.Add(rd.Next(100000, 999999));
list.Sort();
foreach(var item in list)
{
    Console.WriteLine(item);
}
Console.ReadLine();

ArrayList 和 List<T>

ArrayList的优点在于它是可变长数组,可将任意多的数据AddArrayList中,其内部维护的数组当长度不足时,会自动扩容为原来的两倍

ArrayList 的缺点是存入ArrayList中的数据都是Object类型的,如果将值类型进行存入取出操作,就会发生装箱拆箱操作(值类型与引用类型相互转换),而装箱拆箱耗时且影响程序性能的。所以在 .NET2.0 泛型出现后,就提供了List<T>。也就是说,List<T>实际上是ArrayList的泛型版本,由于List<T>不再需要装箱拆箱,可直接存取。虽然List<T>ArrayList操作上是一致的,不过使用前需设置好类型,否则是不允许Add的。

从性能上来说,如果存取的数组仅有一种数据类型,那么List<T>是最优选择。

List<int> list = new List<int>();

如果存取的数组是一个变长且数据类型多样,那最佳的选择仍然是ArrayList

Hashtable 和 Dictionary<T>

HashtableDictionary从数据结构上来说都隶属于哈希表,都是对关键字(键值)进行散列操作,将关键字散列到哈希表的某个槽位中,不同的是它们在处理碰撞时所采用的方法不同。散列函数有可能将不同的关键字散列到哈希表的同一个槽位中,此时称之为发生了碰撞。为了将数据插入进去,则需要另外的方法进行解决。

Hashtable

在.NET模仿Java的过程中,抛弃了HashMap。当有人问到C#中HashTable与HashMap的区别的时候,告诉他C#中是没有HashMap的。

Hashtable用于表示键值对的集合,在.NET Framework中,HashtableSystem.Collections命名空间中提供的一个容器,用于处理和表示类似key-value的键值对的数据结构。其中key通常用于快速查找,同时key也是区分大小写的。而value则用于存储对应key的值。Hashtablekey-value键值对均采用了object类型,所以Hashtable可以支持任何类型的key-value键值对(任何非null对象均可作为keyvalue)。

另外Hashtable可根据键key进行快速查找的value,其特点是不能有重复的key,因此其长度总是一个素数,在扩容后其容量会大于两倍,其加载因子为0.72f。

Hashtable的常见操作

  • HashtableObject.Add(key,value)
    向哈希表中添加一个键值对
  • HashtableObject.Remove(key)
    指定键名后从哈希表中移除某键值对
  • HashtableObject.Clear()
    清空哈希表
  • HashtableObject.Contains(key)
    判断哈希表中是否存在指定键名的数据

Dictonary<T,T>

Dictionary<[key], [value]>

当大量使用key来查找value的时候,Hashtable无疑是最佳选择。由于HashtableArrayList一样都是非泛型的,存入的value均是object类型,因此存储时都会发生装箱拆箱操作,进而影响程序性能。因此,出现了Dictonary<T,T>,也就是说Dictionary<T,T>实际上就是Hashtable的泛型版本。Dictonary<T,T>不仅存取快速而且无需装箱拆箱,同时它优化了算法,其Hashtable是0.72,从而减少了容量的浪费。

Dictionary<string, User> dict = new Dictionary<string, User>();

字典Dictonary同样也是用来表示键值对的集合,由于它是一个泛型,本身又具有集合的功能,因此可见其视为数组。

异同点

  1. 在单线程程序中推荐使用Dictionary,由于具有泛型优势且读取速度较快,其容量利用会更加充分。
  2. 在多线程程序中推荐使用Hashtable,默认的Hashtable允许单线程写入多线程读取,对Hashtable进一步调用Synchronized()方法可获得完全线程安全的类型。而Dictionary是非线程安全的,必须人为使用lock语句进行保护,其效率大减。
  3. 经过测试发现,但key是整型时Dictionary的操作效率要高于Hashtable,而当key是字符串时则Dictionary的效率并没有Hashtable的快。
  4. Dictionary有按插入顺序排列数据的特性,但是当调用Remove()方法删除节点后原来的顺序会被打乱掉。因此在需要体现顺序的场景中使用Dictionary能获得一定的便利。
  5. 遍历Dictionary时会采用插入时的顺序,而遍历Hashtable则是打乱掉的。
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值