目录
数组
数组(Array)必须指定大小,一旦指定了大小就不能改变。
声明数组:
datatype[] arrayName;
其中:
- datatype 用于指定被存储在数组中的元素的类型。
- [ ] 指定数组的秩(维度)。秩指定数组的大小。
- arrayName 指定数组的名称。
例如:
double[] balance;
初始化数组:
double[] balance=new double[10];
赋值给数组:
可以通过索引号赋值给单独的一个数组元素 :
double[] balance = new double[10];
balance[0] = 4500.0;
也可以在声明数组的同时给数组赋值:
double[] balance={ 100.5,23.89,45};
也可以创建并初始化数组:
double[] balance=new double[3]{ 78.2,89.5,123.3}
上述情况可以省略数组的大小:
double[] balance=new double[]{ 78.2,89.5,123.3}
也可以赋值一个数组变量到另一个目标数组变量中,这种情况下,目标和源会指向同一内存地址:
int[] marks=new int[]{89,67,99};
int[] scores=marks;
访问数组元素:
通过索引访问
double salary=balance[1]; // 将balance数组中,索引号为1的值赋给salary变量
看下面这个代码:
从这段代码可以看出:我们要先声明,并初始化数组后,才能使用。通俗点说,声明数组后可以不用赋值,但是要先给个数字让数组容器扩充起来。
改成下面这样:
namespace ConsoleApp1
{
class Program
{
static void Main(string[] args)
{
Random r = new Random();
double[] score=new double[5];//声明数组并初始化
for (int i = 0; i < 5; i++)
{
score[i] = r.Next();
}
}
}
}
集合
预定义常用集合:
- 动态数组 ArrayList
- 列表 List
- 字典 Dictionary
- 队列 Queue
- 栈 Stack
值类型存储在栈中,引用类型存储在堆中
动态数组 ArrayList
前面我们说数组,数组是不可以改变大小的,一旦确定了大小,后面就不能改变了。
但是ArrayList它是动态数组,我们对数组进行增加,删除操作后,数组大小会跟着改变,比如说ArrayList里面有5个元素,后面又加了2个,那它的大小就变成7个,比单纯的数组更智能。
特点:
- 初始化可以不指定大小
- 获取长度,使用Count属性(数组中获取长度使用Length)
- 添加元素使用Add(对象)
- 删除某个元素使用Remove(对象),依据索引删除某个元素使用RemoveAt(索引)
- 访问使用索引 [index]
缺点:存取速度没有数组快,比数组耗费更多的内存,同时它里面存储的Object类型,存在装箱拆箱,那就会有性能的损耗。
namespace ConsoleApp1
{
class Program
{
static void Main(string[] args)
{
ArrayList al = new ArrayList();
Console.WriteLine("Adding some numbers:");
al.Add(45);
al.Add(78);
al.Add(33);
al.Add(56);
al.Add(12);
al.Add(23);
al.Add(9);
Console.WriteLine("Capacity: {0} ", al.Capacity);
Console.WriteLine("Count: {0}", al.Count);
Console.Write("Content: ");
foreach (int i in al)
{
Console.Write(i + " ");
}
Console.WriteLine();
Console.Write("Sorted Content: ");
al.Sort();
foreach (int i in al)
{
Console.Write(i + " ");
}
Console.WriteLine();
Console.ReadKey();
}
}
}
输出:
从上面的代码,我们可以看到Capacity和Count不一样。
我们在声明时,可以对ArrayList进行重载,常见的重载方式有两种:
ArrayList al=new ArrayList();
ArrayList al=new ArrayList(3); // 参数3表示容量,可以容纳3个元素
Capacity 和 Count 分别代表 容量 和 数量
- Capacity表示ArrayList可以包含的元素数,Count表示ArrayList实际包含的元素数
- Capacity可读写,Count只读
当Capacity不够时
我们的 Capacity 如果小了,无法容纳我们实际的元素个数,这时再增加元素时:
如果指定了 Capacity,Capacity 将按指定的 Capacity 的倍数增长(如果 Capacity<=2,将按 2 的倍数增长),比如指定了 Capacity 为 3,那么将按 3、6、9、12、15、18 ……线性的方式增长,直到可以容纳实际的元素个数。
如果没有指定 Capacity 值,Capacity 将按 2的倍数增长,直到可以容纳实际的元素个数。
Capacity 不会自动缩小
当 Capacity 被自动增大后,即使删除了某些元素,Capacity 也不会自动缩小,需要设置 Capacity 来缩小,注意 Capacity 不能小于当前 Count。
namespace ConsoleApp1
{
class Program
{
static void Main(string[] args)
{
ArrayList arr = new ArrayList();
for (int i = 0; i < 3; i++) { arr.Add(i); }
Console.WriteLine(arr.Count); //3
Console.WriteLine(arr.Capacity); //4
arr.RemoveAt(1);
Console.WriteLine(arr.Capacity); //4
Console.WriteLine(arr.Count); //2
Console.WriteLine("*******************************");
ArrayList arr1 = new ArrayList();
for (int i = 0; i < 1; i++) { arr1.Add(i); }
Console.WriteLine(arr1.Count);//1
Console.WriteLine(arr1.Capacity);//4
arr1.RemoveAt(0);
Console.WriteLine(arr1.Capacity);//4
Console.WriteLine(arr1.Count);//0
Console.WriteLine("*******************************");
ArrayList arr2 = new ArrayList(0);
for (int i = 0; i < 3; i++) { arr2.Add(i); }
Console.WriteLine(arr2.Count);//3
Console.WriteLine(arr2.Capacity);//4
arr2.RemoveAt(1);
Console.WriteLine(arr2.Capacity);//4
Console.WriteLine(arr2.Count);//2
Console.WriteLine("*******************************");
ArrayList arr3 = new ArrayList(1);
for (int i = 0; i < 3; i++) { arr3.Add(i); }
Console.WriteLine(arr3.Count);//3
Console.WriteLine(arr3.Capacity);//4
arr3.RemoveAt(1);
Console.WriteLine(arr3.Capacity);//4
Console.WriteLine(arr3.Count);//2
Console.WriteLine("*******************************");
ArrayList arr4 = new ArrayList(2);
for (int i = 0; i < 3; i++) { arr4.Add(i); }
Console.WriteLine(arr4.Count);//3
Console.WriteLine(arr4.Capacity);//4
arr4.RemoveAt(1);
Console.WriteLine(arr4.Capacity);//4
Console.WriteLine(arr4.Count);//2
Console.WriteLine("*******************************");
ArrayList arr5 = new ArrayList(3);
for (int i = 0; i < 3; i++) { arr5.Add(i); }
Console.WriteLine(arr5.Count);//3
Console.WriteLine(arr5.Capacity);//3
arr5.RemoveAt(1);
Console.WriteLine(arr5.Capacity);//3
Console.WriteLine(arr5.Count);//2
Console.WriteLine("*******************************");
ArrayList arr6 = new ArrayList(3);
for (int i = 0; i < 2; i++) { arr6.Add(i); }
Console.WriteLine(arr6.Count); //2
Console.WriteLine(arr6.Capacity);//3
arr6.RemoveAt(1);
Console.WriteLine(arr6.Capacity);//3
Console.WriteLine(arr6.Count);//1
Console.WriteLine("*******************************");
ArrayList arr7 = new ArrayList(4);
for (int i = 0; i < 3; i++) { arr7.Add(i); }
Console.WriteLine(arr7.Count);//3
Console.WriteLine(arr7.Capacity);//4
arr7.RemoveAt(1);
Console.WriteLine(arr7.Capacity);//4
Console.WriteLine(arr7.Count);//2
}
}
}
namespace ConsoleApp1
{
class Program
{
static void Main(string[] args)
{
//ArrayList类
//ArrayList和List都是放在Collections里面的如果要使用需再class类前面加上
//using System.Collections;才可以使用
//ArrayList类的属性,这是不同于方法的东西
//Capacity
//Count
//Item
//有一下几个特点。
/*
1.Array的容量和元素个数是固定的,但是ArrayList是可以改变的
2.Array一次只能对一个元素进行操作,但是ArrayList可以一次追加插入或者移除一组元素
3.ArrayList可以存放多种类型的数据,此时取值要强制转换(拆箱)
4.Array的启示下标是可以设置的,ArrayList的启示下标始终是0
5.Array可以是多维的,ArrayList始终是一维的
*/
//先定义一个ArrayList类
ArrayList a = new ArrayList(10);
//这里()内的大小可以写也可以不写
//我们再定义一个不写大小的
ArrayList b = new ArrayList();
//Capacity获取ArrayList可包含的元素个数
a = new ArrayList(10) { "111", 2, 3, 4, 5, 6, 7, 'A', 8, 9.666, 10 };
//运行后没有报错,证明了ArrayList类中可以存放不同类型数据
//ArrayList里面的类应该是obj类型的
b = a;//这里也可以进行赋值的操作
Console.WriteLine("检查变量a可容纳的元素={0}", a.Capacity.ToString());//20
//使用指定格式将此实例的值转换成其等效的字符串表示,这就是ToString()在这里的作用
//a.Capacity表示选用属性,后面加.ToString()表示调用方法
//Console.WriteLine("检查变量a目前存放的元素个数={0}", a.Capacity);其实这里不加.ToString也是可以的,只是后面懒得改了,,,
//这里显示可以包含20个元素
//但是我们设置的是10个元素为什么会变成20呢?
//因为我们实际输入的元素超过了10,而ArrayList在无法装下的时候会自动让空间翻倍
//所以这里变成了20
b = new ArrayList(10) { 1, 2, 3, 4, 5, 6 };
Console.WriteLine("检查变量b可容纳的元素={0}", b.Capacity.ToString());//10
//而这里我们没有放满10个元素,则可容纳的元素任然是10
b = new ArrayList(10) { 1, 2, 3, 4, 5, 6, 7, 8, 9, 9.66 };
Console.WriteLine("检查变量b可容纳的元素={0}", b.Capacity.ToString());//10
b = new ArrayList(10) { 1, 2, 3, 4, 5, 6, 7, 8, 9, "12" };
Console.WriteLine("检查变量b可容纳的元素={0}", b.Capacity.ToString());//10
b = new ArrayList(10) { 1, 2, 3, 4, 5, 6, 7, 8, 9, "122222222" };
Console.WriteLine("检查变量b可容纳的元素={0}", b.Capacity.ToString());//10
b = new ArrayList(10) { 1, 2, 3, 4, 5, 6, 7, 8, 9, "AB" };
Console.WriteLine("检查变量b可容纳的元素={0}", b.Capacity.ToString());//10
b = new ArrayList(10) { 1, 2, 3, 4, 5, 6, 7, 8, 9, "AB12" };
Console.WriteLine("检查变量b可容纳的元素={0}", b.Capacity.ToString());//10
//通过对上面数据的测试,我们发现,""字符串的数据也只占用一个元素
//Count表示元素现在包含的元素的数量
//这里直接继续使用a和b做对比
Console.WriteLine("检查变量a目前存放的元素个数={0}", a.Count);
Console.WriteLine("检查变量b目前存放的元素个数={0}", b.Count);
//Item[]
//即获取指定索引处的元素。
//和数组的使用没有区别
int i = 0;
Console.WriteLine("获得a指定索引{0}处的数据={1}", ++i, a[i]);
}
}
}
List<T>泛型集合
比ArrayList执行的更好,而且更安全
namespace ConsoleApp1
{
class Program
{
static void Main(string[] args)
{
List<Dog> Ldog = new List<Dog>();
Ldog.Add(new Dog("A"));
Ldog.Add(new Dog("B"));
Ldog.Add(new Dog("C"));
Console.WriteLine(Ldog.Count);//3
Console.WriteLine(Ldog.Capacity);//4
}
}
class Dog {
public Dog(string name) { }
}
}
字典Dictionary<TKey,TValue>
字典是以键值对的形式存储,每个值对应唯一的键。访问是通过键
使用:
- 数量 Count
- 增加 Add(key,value)
- 删除 Remove
- 访问 [key]
namespace ConsoleApp1
{
class Program
{
static void Main(string[] args)
{
Dictionary<string, Dog> dic = new Dictionary<string, Dog>();
dic.Add("jack", new Dog());
dic.Add("tom", new Dog());
Console.WriteLine(dic.Count); //2
foreach (var item in dic)
{
Console.WriteLine(item.Key); //依次输出jack tom
}
}
}
class Dog {
public Dog() { }
}
}
栈 Stack
栈是先进后出,后进先出(LIFO Last In First Out 后进先出法)。可以把它想象成一个开口的羽毛球筒。
栈的操作:
- 出栈 Pop 例如把羽毛球取出来
- 入栈 Push 例如把羽毛球放进去
- 获取栈顶元素 Peek 例如筒里12个球,获取第12个元素
namespace ConsoleApp1
{
class Program
{
static void Main(string[] args)
{
Stack s = new Stack();
s.Push(1);
s.Push(2);
foreach (var item in s)
{
Console.WriteLine(item); //依次输出 2 1
}
Stack<Pet> s2 = new Stack<Pet>();
s2.Push(new Dog("jack"));
s2.Push(new Cat("tom"));
foreach (var item in s2)
{
item.PrintName(); // 依次输出 tom jack
}
}
}
class Pet {
private string name;
public string Name { get => name; set => name = value; }
public Pet(string _name) {
Name = _name;
}
public void PrintName() {
Console.WriteLine(Name);
}
}
class Cat:Pet {
public Cat(string name) : base(name) { }
}
class Dog:Pet {
public Dog(string name) : base(name) { }
}
}
队列 Queue
队列是先进先出(FIFO First In First Out),类似两端开口的羽毛球筒
队列的使用:
- 入队 Enqueue
- 出队 Dequeue
namespace ConsoleApp1
{
class Program
{
static void Main(string[] args)
{
Queue q = new Queue();
q.Enqueue(1);
q.Enqueue(2);
foreach (var item in q)
{
Console.WriteLine(item);// 依次输出 1 2
}
q.Dequeue();
foreach (var item in q)
{
Console.WriteLine(item); // 输出2
}
Queue<Pet> q2 = new Queue<Pet>();
q2.Enqueue(new Dog("jack"));
q2.Enqueue(new Dog("tom"));
foreach (var item in q2)
{
item.PrintName(); // 依次输出 jack tom
}
q2.Dequeue();
foreach (var item in q2)
{
item.PrintName(); // 输出tom
}
}
}
class Pet {
private string name;
public string Name { get => name; set => name = value; }
public Pet(string _name) {
Name = _name;
}
public void PrintName() {
Console.WriteLine(Name);
}
}
class Cat:Pet {
public Cat(string name) : base(name) { }
}
class Dog:Pet {
public Dog(string name) : base(name) { }
}
}