C#复习笔记(五)
ArrayList
using System.Collections;
是C#为我们封装好的类,帮助我们实现了许多方法
本质是一个object类型的数组
ArrayList array = new ArrayList();
增:array.Add();
array.AddRange(array2); //把另一个容器的内容增加到后面
删:array.Remove(); //移除指定元素,从头找,找到就删掉
array.RemoveAt(); //移除指定位置的元素
array.Clear(); //清空
查:array.Contains(); //判断元素是否存在
IndexOf(); //正向查找
LastIndexOf(); //反向查找,返回的索引按正向来
改:array[0] = "114514";
插:array.Insert(1,"1919810");
遍历:
for(int i = 0; i < array.Count; i++){}
foreach(var item in array){} //迭代器遍历
装箱拆箱:
int x = 1;
array[0] = x; //装箱
x = (int)array[0]; //拆箱
栈 Stack
本质也是object数组,只是封装了特殊的存储规则
栈是一种先进后出的数据结构,跟取出腌菜缸里的腌菜一样。
先存入的数据后获取,后存入的先获取
Stack stack = new Stack()
增:stack.Push(); //只能一个一个的放入
取(删,也称弹栈):stack.Pop();
查(只查看栈顶,不会取出):stack.Peek();
stack.Contains(); //是否存在
改:栈无法改变其中的元素,只能放和取
只能使用stack.Clear(); 清空栈
遍历:
无法使用for循环遍历,因为没有提供用[]访问的接口
可用foreach遍历或转换为object数组后遍历
foreach(var item in stack){};
object[] array = stack.ToArray();
for(int i = 0; i < array.Length; i++){}
循环弹栈:
while(stack.Count > 0)
{
object o = stack.Pop();
Console.Write(o);
}
可装拆箱
队列 Queue
本质还是object[]数组,也封装了不明物体
队列是一种先进先出的数据结构
先存入的数据先获取,后存入的后获取(先进先出)
Queue queue = new Queue();
增:queue.Enqueue();
删(取):queue.Dequeue(); //取出先加入的对象
查:queue.Peek(); //看队列头部元素是什么
queue.Contains(); //查看元素是否存在
改:也不能改,只能进出队列
只能使用queue.Clear(); 清空队列
遍历:
无法使用for循环遍历,因为没有提供用[]访问的接口
同栈使用foreach和转换为object[]
循环出列:
while(queue.Count>0)
{
object o = queue.Dequeue();
Console.Write(o);
}
可装拆箱
哈希表 HashTable
又称散列表,基于键的哈希代码组织起来的键-值对
提高数据查询的效率
使用键来访问集合中的元素
Hashtable hashtable = new Hashtable();
增:hashtable.Add( 1 , "14514");
删:hashtable.Remove(1);
删除不存在的键不会有反应
hashtable.Clear();
查:hashtable[1];
找不到会返回空
hashtable.Contains();
hashtable.ContainsKey(); //两个查找方法没有区别,都是查找是否存在键
hashtable.ContainsValue(); //查找值
改:hashtable[1] = 1919;
遍历:
无法用for循环遍历
遍历所有的键:
foreach(object item in hashtable.Keys)
{
Console.Write(hashtable[item]);
}
遍历所有的值:
foreach(object item in hashtable.Values)
{
Console.Write(item);
}
键值对一起遍历:
foreach(DictionaryEntry item in hashtable)
{
Console.Write(item.Keys + item.Value);
}
迭代器遍历:
IDictionaryEnumerator enumerator = hashtable.GetEnumerator();
bool flag = enumerator.MoveNext();
while(flag)
{
Console.Write(enumerator.Key + enumerator.Value)
}
可装拆箱
泛型
实现了类型参数化,达到代码重用的目的,相当于类型占位符
通过类型参数化来实现同一份代码上操作多种类型
定义类或方法是使用替代符代表变量类型
当真正使用类或者方法时再具体指定类型
泛型分类
泛型占位字母可以有多个,用逗号分开
泛型类:class 类名<泛型占位字母>
class TestClass<T>
{
public T value;
}
TestClass<int> t = new TestClass<int>();
t.value = 114514;
Console.Write(t.value)
泛型接口:interface 接口名<泛型占位字母>
interface TestInterface<T>
{
T Value{get;set;}
}
//继承泛型接口
class Test : TestInterface<int>{}
泛型函数:函数名<泛型占位字母>(参数列表)
普通类中的泛型方法:
class Test
{
public void TestFun<T>(T value)
{
Console.Write(value);
}
//重载用泛型类型在函数内写逻辑
public void TestFun<T>()
{
T t = default(T); //确保变量 t 被安全初始化
}
//重载返回值为泛型
public T TestFun<T>(string v)
{
return default(T); //可作为返回值
}
}
泛型类中的泛型方法:
public Test<T> //类名字一样,但加了泛型就位不同类型
{
public T value;
public void TestFun(T t){} //不为泛型方法,T是泛型类申明时就确定的,使用这个函数的时候就不能动态变化
public void TestFun<K>(K k) //泛型字母T被类使用,需要更换
{
Console.Write(k);
}
}
泛型的作用
1、不同类型对象的相同逻辑处理就可选择泛型
2、使用泛型可以一定程度避免装拆箱
泛型约束 where
where 约束字母:约束条件
约束条件:
1、值类型 where T:struct
2、引用类型 where T:class
3、存在无参公共构造函数 where T:new()
4、某个类本身或者其派生类 where T:类名
5、某个接口的派生类型 where T:接口名
6、另一个泛型类型本身或者派生类型 where T:另一个泛型字母
约束可以组合使用,用“,”隔开计科
多个泛型也可以同时约束,where T:struct where K:class
常用泛型数据结构类
List、Dictionary、顺序存储和链式存储、Linkedlist、泛型栈和队列
List
本质是一个可变类型的泛型数组
List<int> list = new List<int>();
增:list.Add(); listAddRange();
删:.Remove(); .RemoveAt();
查:.IndexOf(); .LastIndexOf();
改:list[0] = 114514; Insert(0,114)
for和foreach遍历
Dictionary
可以理解为拥有泛型的Hashtable(键值对)
键值对类型从Hashtable的object变味了可以自己制定的泛型
Dictionary<int, string> dictionary = new Dictionary<int, string>();
增:dictionary.Add();
删:.Remove(); .Clear()
查:dictionary[1]; ContainsKey(); ContainsValue();
改:dictionary[1]
foreach、KeyValuePair、迭代器
顺序存储和链式存储
顺序存储:
用一组地址连续的存储单元依次存储线性表的各个数据元素
数组、Stack、Queu、List、ArrayList
链式存储:
用一组任意的存储单元存储到线性表中的各个数据元素
单向、双向、循环链表
实现一个单链表:
class LinkedNode<T>
{
public T value;
public LinkedNode<T> nextNode; //存储的下一个元素是谁
public LinkedNode(T value)
{
this.value = value;
}
}
LinkedNode<int> node = new LinkedNode<int>(1);
LinkedNode<int> node2 = new LinkedNode<int>(2);
node.nextNode = node2;
LinkedList
本质是一个可变类型的泛型双向链表
LinkedList<int> linkedList = new LinkedList<int>();
增:linkedList.AddFirst(); //头部增加元素
.AddLast(); //尾部增加元素
.AddAfter(); //某个节点之后添加
.AddBefore(); //某个节点之前添加
删:.RemoveFirst(); RemoveLast(); //移出头结点和尾结点
查:无法直接通过下标获取中间元素
linkedList.First; //头结点
linkedList.Last; //尾结点
linkedList.Find(); //查找指定位置元素
.Contains();
改:先得到结点才能改变其中的值
linkedList .First.Value = 114514;
遍历:
//foreach能直接得到里面的值
foreach(int item in linkedList)
{
Console.WriteLine(item);
}
//从头到尾遍历
LinkedListNode<int> nowNode = linkedList.First; //nowNode用于存储的临时变量
while(nowNode != null)
{
Console.Write(nowNode.Value);
nowNode = nowHead.Next;
}
//从尾到头遍历
nowNode = linkedList.Last; //nowNode用于存储的临时变量
while(nowNode != null)
{
Console.Write(nowNode.Value);
nowNode = nowHead.Previous;
}
泛型栈和队列
使用上与Stack和Queue一样
Stack<int> stack = new Stack<int>();
Queue<object> queue = new Queue<object>();