2.简单数据结构类-ArrayList
2.1 知识点
练习题回顾
C#核心中索引器的练习题
自定义一个整形数组类,该类中有一个整形数组变量,为它封装增删查改的方法。
ArrayList的本质
ArrayList是一个C#为我们封装好的类,它的本质是一个object
类型的数组(可以存储任何类型的数组)。ArrayList类帮助我们实现了很多方法,比如数组的增删查改。
ArrayList的申明
需要引用命名空间using System.Collections;
包含一些集合类。
ArrayList arrayList = new ArrayList();
ArrayList的增删查改和遍历
增
当前arrayList
中的元素有:
{}
Add方法:直接在ArrayList
末尾增加对应元素。
arrayList.Add(1);
arrayList.Add("123");
arrayList.Add(true);
arrayList.Add(new object());
arrayList.Add(new Test());
arrayList.Add(1);
arrayList.Add(true);
AddRange方法:范围增加(批量增加,把另一个ArrayList
容器里面的所有元素加到当前ArrayList
容器后面)。
ArrayList arrayList2 = new ArrayList();
arrayList2.Add("我是arrayList2中的元素");
arrayList.AddRange(arrayList2); // 会把arrayList2中所有元素拼接在arrayList后面
Insert方法:往指定位置插入元素。
arrayList.Insert(8, "我是arrayList中索引为8的元素");
Console.WriteLine(arrayList[8]); // 我是arrayList中索引为8的元素
增完之后arrayList
中的元素有:
{ 1, 123, True, System.Object, Lesson01_ArrayList.Test, 1, True, 我是arrayList2中的元素, 我是arrayList中索引为8的元素 }
删
当前arrayList
中的元素有:
{ 1, 123, True, System.Object, Lesson01_ArrayList.Test, 1, True, 我是arrayList2中的元素, 我是arrayList中索引为8的元素 }
Remove方法:移除指定元素,从头找,找到即删,假如有多个只会删除第一个。
arrayList.Remove(1); // 删除指定元素1
RemoveAt方法:移除指定位置的元素,索引从0开始。
arrayList.RemoveAt(2); // 删除索引为2的System.Object
Clear方法:清空ArrayList
中所有元素。
// arrayList.Clear(); // 为了后面测试方便,先注释
删完之后arrayList
中的元素有:
{ 123, True, Lesson01_ArrayList.Test, 1, True, 我是arrayList2中的元素, 我是arrayList中索引为8的元素 }
查
当前arrayList
中的元素有:
{ 123, True, Lesson01_ArrayList.Test, 1, True, 我是arrayList2中的元素, 我是arrayList中索引为8的元素 }
ArrayList[x]索引器get:得到指定位置x的元素。
Console.WriteLine(arrayList[0]); // 123
Contains方法:传入元素,查看元素是否存在。存在返回true
,否则返回false
。
if (arrayList.Contains("123"))
{
Console.WriteLine("存在123"); // 存在123
}
IndexOf方法:正向查找元素位置。
// 找到的返回值是位置,找不到返回值是-1,假如有多个,只会返回从头数第一找到的元素的位置
int index = arrayList.IndexOf(true);
Console.WriteLine(index); // 1 找到从头数第一个true在索引1位置,假如有两个true只会返回第一个true所在的位置
Console.WriteLine(arrayList.IndexOf(false)); // -1 找不到false这个元素
LastIndexOf方法:反向查找元素位置。
// 返回时从头开始的索引数
index = arrayList.LastIndexOf(true);
Console.WriteLine(index); // 4 找到从末尾数第一个true在索引4位置,假如有两个true只会返回从末尾数第一个true所在的位置
改
当前arrayList
中的元素有:
{ 123, True, Lesson01_ArrayList.Test, 1, True, 我是arrayList2中的元素, 我是arrayList中索引为8的元素 }
ArrayList[x] = “”索引器set:修改指定位置x的元素。
Console.WriteLine(arrayList[0]); // 123
arrayList[0] = "999";
Console.WriteLine(arrayList[0]); // 999
改完之后arrayList
中的元素有:
{ 999, True, Lesson01_ArrayList.Test, 1, True, 我是arrayList2中的元素, 我是arrayList中索引为8的元素 }
遍历
当前arrayList
中的元素有:
{ 999, True, Lesson01_ArrayList.Test, 1, True, 我是arrayList2中的元素, 我是arrayList中索引为8的元素 }
Count属性:返回ArrayList
的长度,具体存了多少个。
Console.WriteLine(arrayList.Count); // 7
Capacity属性:返回ArrayList
的容量。
// 每次长度大于容量时会扩容至当前容量的两倍,避免产生过多的垃圾
Console.WriteLine(arrayList.Capacity); // 16
普通for
循环遍历:
Console.WriteLine("**********普通for循环遍历**********");
for (int i =
0; i < arrayList.Count; i++)
{
Console.WriteLine(arrayList[i]);
//{ 999, True, Lesson01_ArrayList.Test, 1, True, 我是arrayList2中的元素, 我是arrayList中索引为8的元素 }
}
迭代器foreach
遍历:
Console.WriteLine("**********迭代器foreach遍历**********");
foreach (object item in arrayList)
{
Console.WriteLine(item);
//{ 999, True, Lesson01_ArrayList.Test, 1, True, 我是arrayList2中的元素, 我是arrayList中索引为8的元素 }
}
ArrayList的装箱拆箱
ArrayList本质上是一个可以自动扩容的object
数组,由于用object
来存储数据,自然存在装箱拆箱。当往其中进行值类型存储时就是在装箱,当将值类型元素取出来转换使用时,就存在拆箱。
实例:
int k = 1;
arrayList[0] = k; // 装箱,ArrayList的元素是object类型的,把值类型用引用类型来存
k = (int)arrayList[0]; // 拆箱,ArrayList的元素是object类型的,把引用类型强转成值类型
2.2 知识点代码
using System;
using System.Collections;
namespace Lesson01_ArrayList
{
class Test
{
}
class Program
{
static void Main(string[] args)
{
Console.WriteLine("ArrayList");
#region 练习题回顾
//C#核心中 索引器的练习题
//自定义一个整形数组类,该类中有一个整形数组变量,为它封装增删查改的方法
#endregion
#region 知识点一 ArrayList的本质
//ArrayList是一个C#为我们封装好的类,
//它的本质是一个object类型的数组(可以存储任何类型的数组),
//ArrayList类帮助我们实现了很多方法,
//比如数组的增删查改
#endregion
//主函数内
#region 知识点二 ArrayList的申明
//需要引用命名空间using System.Collections; 包含一些集合类
ArrayList arrayList = new ArrayList();
#endregion
#region 知识点三 ArrayList的增删查改和遍历
#region 增
//当前arrayList中的元素有
//{}
//Add方法 直接在ArrayList末尾增加对应元素
arrayList.Add(1);
arrayList.Add("123");
arrayList.Add(true);
arrayList.Add(new object());
arrayList.Add(new Test());
arrayList.Add(1);
arrayList.Add(true);
//AddRange方法 范围增加(批量增加 把另一个ArrayList容器里面的所有元素加到当前ArrayList容器后面)
ArrayList arrayList2 = new ArrayList();
arrayList2.Add("我是arrayList2中的元素");
arrayList.AddRange(arrayList2);//会把arrayList2中所有元素拼接在arrayList后面
//Insert方法 往指定位置插入元素
arrayList.Insert(8, "我是arrayList中索引为8的元素");
Console.WriteLine(arrayList[8]);//我是arrayList中索引为8的元素
//增完之后arrayList中的元素有
//{ 1,123,True,System.Object,Lesson01_ArrayList.Test,1,True,我是arrayList2中的元素,我是arrayList中索引为8的元素}
#endregion
#region 删
//当前arrayList中的元素有
//{ 1,123,True,System.Object,Lesson01_ArrayList.Test,1,True,我是arrayList2中的元素,我是arrayList中索引为8的元素}
//Remove方法 移除指定元素 从头找 找到删 假如有多个只会删除第一个
arrayList.Remove(1);//删除指定元素1
//RemoveAt方法 移除指定位置的元素 索引从0开始
arrayList.RemoveAt(2);//删除索引为2的System.Object
//Clear方法 清空ArrayList中所有元素
//arrayList.Clear();//为了后面测试方便 先注释
//删完之后arrayList中的元素有
//{123,True,Lesson01_ArrayList.Test,1,True,我是arrayList2中的元素,我是arrayList中索引为8的元素}
#endregion
#region 查
//当前arrayList中的元素有
//{123,True,Lesson01_ArrayList.Test,1,True,我是arrayList2中的元素,我是arrayList中索引为8的元素}
//ArrayList[x] 得到指定位置x的元素
Console.WriteLine(arrayList[0]);//123
//Contains方法 传入元素 查看元素是否存在 存在返回true 否则返回false
if ( arrayList.Contains("123") )
{
Console.WriteLine("存在123");//存在123
}
//IndexOf方法 正向查找元素位置
//找到的返回值是位置 找不到返回值是-1
//假如有多个 只会返回从头数第一找到的元素的位置
//之前往arrayList添加过 true 这个元素 找得到
int index = arrayList.IndexOf(true);
Console.WriteLine(index);//1 找到从头数第一个ture在索引1位置 假如有两个ture只会返回第一个true所在的位置
Console.WriteLine(arrayList.IndexOf(false));//-1 找不到false这个元素
//LastIndexOf方法 反向查找元素位置
//返回时从头开始的索引数
index = arrayList.LastIndexOf(true);
Console.WriteLine(index);//4 找到从末尾数第一个ture在索引4位置 假如有两个ture只会返回从末尾数第一个true所在的位置
#endregion
#region 改
//当前arrayList中的元素有
//{123,True,Lesson01_ArrayList.Test,1,True,我是arrayList2中的元素,我是arrayList中索引为8的元素}
//ArrayList[x] = "" 修改指定位置x的元素
Console.WriteLine(arrayList[0]);//123
arrayList[0] = "999";
Console.WriteLine(arrayList[0]);//999
//改完之后arrayList中的元素有
//{999,True,Lesson01_ArrayList.Test,1,True,我是arrayList2中的元素,我是arrayList中索引为8的元素}
#endregion
#region 遍历
//当前arrayList中的元素有
//{999,True,Lesson01_ArrayList.Test,1,True,我是arrayList2中的元素,我是arrayList中索引为8的元素}
//Count属性 返回ArrayList的长度 具体存了多少个
Console.WriteLine(arrayList.Count);//7
//Capacity属性 返回ArrayList的容量
//每次长度大于容量时会扩容至当前容量的两倍 避免产生过多的垃圾
Console.WriteLine(arrayList.Capacity);//16
//普通for循环遍历
Console.WriteLine("**********普通for循环遍历**********");
for (int i = 0; i < arrayList.Count; i++)
{
Console.WriteLine(arrayList[i]);
//{999,True,Lesson01_ArrayList.Test,1,True,我是arrayList2中的元素,我是arrayList中索引为8的元素}
}
//迭代器foreach遍历
Console.WriteLine("**********迭代器foreach遍历**********");
foreach (object item in arrayList)
{
Console.WriteLine(item);
//{999,True,Lesson01_ArrayList.Test,1,True,我是arrayList2中的元素,我是arrayList中索引为8的元素}
}
#endregion
#endregion
#region 知识点四 ArrayList的装箱拆箱
//ArrayList本质上是一个可以自动扩容的object数组,
//由于用万物之父来存储数据,自然存在装箱拆箱。
//当往其中进行值类型存储时就是在装箱,当将值类型元素取出来转换使用时,就存在拆箱。
//所以ArrayList尽量少用,之后我们会学习更好的数据容器。
//实例
int k = 1;
arrayList[0] = k;//装箱 arrayList的元素是object类型的 把值类型用引用类型来存
k = (int)arrayList[0];//拆箱 arrayList的元素是object类型的 把引用类型强转成值类型
#endregion
}
}
}
2.3 练习题
请简述ArrayList和数组的区别
- ArrayList本质上是一个object数组的封装,而数组是一种数据结构,用来存储固定大小的相同类型元素的集合。
- ArrayList可以动态增长和缩减,而数组的长度在创建时就已经确定,不能动态改变。
- 数组可以指定存储类型,而ArrayList默认存储的是object类型。
- 数组的增删操作需要手动实现,而ArrayList提供了方便的API来实现增删操作。
- 使用ArrayList时可能存在装箱拆箱的问题,而数组不会存在这个问题,除非是object数组。
- 数组的长度属性为Length,而ArrayList的长度属性为Count。
创建一个背包管理类,使用ArrayList存储物品,实现购买物品,卖出物品,显示物品的功能。购买与卖出物品会导致金钱变化
class语句块外 namespace语句块内
// 背包管理类
class BagMgr
{
// 背包中的物品列表
private ArrayList items;
// 背包中的金钱
private int money;
// 背包管理类构造函数,初始化背包中的金钱和物品列表
public BagMgr(int money)
{
this.money = money;
items = new ArrayList();
}
// 购买物品
public void BuyItem(Item item)
{
// 检测物品信息是否正确
if (item.num <= 0 || item.money < 0)
{
Console.WriteLine("请传入正确的物品信息");
return;
}
// 检查金钱是否足够
if (this.money < item.money * item.num)
{
Console.WriteLine("买不起,钱不够");
return;
}
// 扣除金钱
this.money -= item.money * item.num;
Console.WriteLine("购买{0}{1}个,花费{2}钱", item.name, item.num, item.money * item.num);
Console.WriteLine("剩余{0}元钱");
// 检查背包中是否已有该物品,如有,数量叠加
foreach (Item i in items)
{
if (i.id == item.id)
{
i.num += item.num;
return;
}
}
// 若背包中没有该物品,则添加到背包
items.Add(item);
}
// 卖出物品
public void SellItem(Item item)
{
for (int i = 0; i < items.Count; i++)
{
if ((items[i] as Item).id == item.id)
{
int num = Math.Min((items[i] as Item).num, item.num); // 实际卖出的数量
string name = (items[i] as Item).name;
int sellMoney = (int)(num * (items[i] as Item).money * 0.8f); // 打八折
this.money += sellMoney; // 加到总金币中
Console.WriteLine("卖了{0}{1}个,赚了{2}钱", name, num, sellMoney);
Console.WriteLine("目前拥有{0}元钱", this.money);
// 减少背包中物品数量,如果数量为0,则从背包中移除该物品
(items[i] as Item).num -= num;
if ((items[i] as Item).num == 0)
{
items.RemoveAt(i);
}
return;
}
}
}
// 显示物品
public void ShowItem()
{
foreach (Item item in items)
{
Console.WriteLine("有{0}{1}个", item.name, item.num);
}
Console.WriteLine("当前拥有{0}元钱", this.money);
}
}
// 物品类
class Item
{
public int id; // 物品唯一ID
public int money; // 物品价格
public string name; // 物品名称
public int num; // 物品数量
// 物品类构造函数
public Item(int id, int money, string name, int num)
{
this.id = id;
this.money = money;
this.name = name;
this.num = num;
}
}
主函数内
BagMgr myBag = new BagMgr(99999); // 初始化背包,金钱99999
// 创造几个物品
Item item1 = new Item(1, 10, "红药", 10);
Item item2 = new Item(2, 20, "蓝药", 10);
Item item3 = new Item(3, 999, "屠龙刀", 1);
myBag.BuyItem(item1); // 购买红药10个,花费100钱,剩余99899元钱
myBag.BuyItem(item2); // 购买蓝药10个,花费200钱,剩余99699元钱
myBag.BuyItem(item3); // 购买屠龙刀1个,花费999钱,剩余98700元钱
myBag.SellItem(item3); // 卖了屠龙刀1个,赚了799钱,目前拥有99499元钱
myBag.SellItem(1, 1); // 卖了红药1个,
赚了8钱,目前拥有99507元钱
myBag.SellItem(1, 1); // 卖了红药1个,赚了8钱,目前拥有99515元钱
myBag.SellItem(2, 1); // 卖了蓝药1个,赚了16钱,目前拥有99531元钱
myBag.SellItem(2, 1); // 卖了蓝药1个,赚了16钱,目前拥有99547元钱
2.4 练习题代码
using System;
using System.Collections;
namespace Lesson01_练习题
{
#region 练习题一
//请简述ArrayList和数组的区别
#region 答案
//ArrayList本质上是一个object数组的封装
//1.ArrayList可以不用一开始就定长,单独使用数组是定长的
//2.数组可以指定存储类型,ArrayList默认为object类型
//3.数组的增删需要我们自己去实现,ArrayList帮我们封装了方便的API来使用
//4.ArrayList使用时可能存在装箱拆箱,数组使用时只要不是object数组那就不存在这个问题
//5.数组长度为Length, ArrayList长度为Count
#endregion
#endregion
//class语句块外 namespace语句块内
#region 练习题二
//创建一个背包管理类,使用ArrayList存储物品,
//实现购买物品,卖出物品,显示物品的功能。购买与卖出物品会导致金钱变化
//背包管理类
class BagMgr
{
//背包中的物品列表
private ArrayList items;
//背包中有多少钱
private int money;
//背包管理类构造函数 初始化背包中有多少钱和背包中的物品列表
public BagMgr( int money )
{
this.money = money;
items = new ArrayList();
}
//购买物品 传入一个item
public void BuyItem(Item item)
{
//检测传入的item中的信息是否正确
if( item.num <= 0 || item.money < 0 )
{
Console.WriteLine("请传入正确的物品信息");
return;
}
//检查钱够不够
if( this.money < item.money*item.num )
{
//买不起 钱不够
Console.WriteLine("买不起 钱不够");
return;
}
//钱够的话 减钱
this.money -= item.money * item.num;
Console.WriteLine("购买{0}{1}个花费{2}钱", item.name, item.num, item.money * item.num);
Console.WriteLine("剩余{0}元钱", this.money);
//如果想要叠加物品 可以在前面先判断 是否有这个物品 然后加数量
//只能遍历背包中的物品列表来判断
for (int i = 0; i < items.Count; i++)
{
if( (items[i] as Item).id == item.id )
{
//叠加数量
(items[i] as Item).num += item.num;
return;
}
}
//如果走到这说明当前背包里没有这类item 把这一类物品加到背包中
items.Add(item);
}
//卖出物品 传入一个item
public void SellItem(Item item)
{
//遍历背包
for (int i = 0; i < items.Count; i++)
{
//如何判断 卖的东西我背包里有没有?
//我们要判断 卖的物品 我有没有 一般不这样判断
//if(items[i] == item)
//{
//}
//这其实是在比较 两个引用地址 指向的是不是同一个房间
//或者说
//比较的是 两个item在栈上存的指向堆中的值 想不想等
//不是传的new出来的同一个对象 肯定不相等的
//通过id判断卖的东西我背包里有没有
if ( (items[i] as Item).id == item.id )
{
//创建临时变量方便记录
int num = 0;//实际卖了多少个item
string name = (items[i] as Item).name;//item名
int money = (items[i] as Item).money;//item单价
//卖东西的时候有两种情况
//1.假如要卖的东西比我身上的少 说明我有更多这个item 直接卖
if ((items[i] as Item).num > item.num)
{
//有更多这个item 直接赋值实际卖了多少个item
num = item.num;
}
//2.假如要卖的东西比我身上的多 说明我没有那么多这个item 只能卖我当前有多少个这个item 全部卖完
else
{
//实际卖了多少个item 就是 我拥有多少个这个item
num = (items[i] as Item).num;
//卖完了 这个item就从背包上移除了
items.RemoveAt(i);
}
int sellMoney = (int)(num * money * 0.8f);//卖出去赚的总价 打八折
this.money += sellMoney;//加到总金币中
Console.WriteLine("卖了{0}{1}个,赚了{2}钱", name, num, sellMoney);
Console.WriteLine("目前拥有{0}元钱", this.money);
return;
}
}
}
//卖出物品 传入物品的id和数量
public void SellItem(int id, int num = 1)
{
//直接调用上面写好的重载卖出物品方法
//直接构造一个Item类 把ID和数量两个关键信息设置了即可 就可以卖了
Item item = new Item(id, num);
SellItem(item);
}
//显示物品
public void ShowItem()
{
//临时变量 用于遍历
Item item;
//遍历背包
for (int i = 0; i < items.Count; i++)
{
//赋值临时变量 打印输出
item = items[i] as Item;
Console.WriteLine("有{0}{1}个", item.name, item.num);
}
Console.WriteLine("当前拥有{0}元钱", this.money);
}
}
//物品类
class Item
{
//物品唯一ID 来区分物品的种类
public int id;
//物品多少钱(单价)
public int money;
//物品名字
public string name;
//物品信息
//public string tips;
//物品数量
public int num;
//物品类构造函数
public Item(int id, int num)
{
this.id = id;
this.num = num;
}
public Item(int id, int money, string name, int num)
{
this.id = id;
this.money = money;
this.name = name;
this.num = num;
}
}
#endregion
class Program
{
static void Main(string[] args)
{
Console.WriteLine("ArrayList练习题");
//主函数内
#region 练习题二
BagMgr myBag = new BagMgr(99999);//new出背包 初始化金币99999
//创造几个物品
Item item1 = new Item(1, 10, "红药", 10);
Item item2 = new Item(2, 20, "蓝药", 10);
Item item3 = new Item(3, 999, "屠龙刀", 1);
myBag.BuyItem(item1);//购买红药10个花费100钱 剩余99899元钱
myBag.BuyItem(item2);//购买蓝药10个花费200钱 剩余99699元钱
myBag.BuyItem(item3);//购买屠龙刀1个花费999钱 剩余98700元钱
myBag.SellItem(item3);//卖了屠龙刀1个,赚了799钱 目前拥有99499元钱
myBag.SellItem(1, 1);//卖了红药1个,赚了8钱 目前拥有99507元钱
myBag.SellItem(1, 1);//卖了红药1个,赚了8钱 目前拥有99515元钱
myBag.SellItem(2, 1);//卖了蓝药1个,赚了16钱 目前拥有99531元钱
myBag.SellItem(2, 1);//卖了蓝药1个,赚了16钱 目前拥有99547元钱
#endregion
}
}
}
转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。可以在下面评论区评论,也可以邮件至 785293209@qq.com