zoukankan      html  css  js  c++  java
  • C#高级编程四十八天----列表

    C#中的List

    C#deList怎么样?List<T>类是ArrayList类的泛型等效类,该类使用大小可按需动态增长的数组实现List<T>泛型接口.

    泛型的优点:它为使用C#语言编写面向对象程序添加了极大的效力和灵活性,不会强行对值类型进行装箱和拆箱,或对引用类型进行向下强制类型转化,所以性能得到提高.

    性能注意事项:再决定使用List<T>还是使用ArrayList(两者具有类似的功能),记住IList<T>类在大多数情况下运行得更好而且是类型安全的.假设对IList<T>类的类型T使用引用类型,则两个类的行为是全然同样的,可是假设对类型T使用值类型,则须要考虑实现和装箱问题.

    C#List的基础经常用法:

    一.声明:

    1.  List<T> list=new List<T>():

    T为列表中元素类型,如今以string类型作为样例:

    List<string> list=new List<string>():

    2.List<T> list = new List<T>(IEnumerable<T> collection);

    以一个集合作为參数创建List:

                string[] temArr = { "Ha", "Hunter", "Tom", "Lily", "Jay", "Jim", "Kuku", "Locu" };

                List<string> testList = new List<string>(temArr);

    二.加入元素:

    1. List.Add( Titem)加入一个元素

    比如:testList.Add(“hahaha”);

    2. List.AddRange(IEnumerable <T> collection)  加入一组元素

    :            string[] temArr = { "Ha", "Hunter", "Tom", "Lily", "Jay", "Jim", "Kuku", "Locu" };

                List<string> testList = new List<string>();

                testList.AddRange(temArr);

    3.  Insert(int index ,T item) ; index位置加入一个元素

    :testList.Insert(1,”hello”);

    三.遍历List中的元素:

    案例:

                string[] temArr = { "Ha", "Hunter", "Tom", "Lily", "Jay", "Jim", "Kuku", "Locu" };

                List<string> testList = new List<string>();

                testList.AddRange(temArr);

                foreach (var item in testList)

                {

                    Console.WriteLine(item);

                }

    四.删除元素:

    1.List.Remove(T item)删除一个值

    :mList.Remove(“hahaha”);

    2.List.RemoveAt(int index);删除下标为index 的元素

    :mList.RemoveAt(0);

    3.List.RemoveRange(int index , int count);从下标index開始,删除count个元素

    :mList.RemoveRange(3,2);

    五.推断某个元素是否在该List:

    List.Contains(T item) 返回truefalse,非常有用

    :            string[] temArr = { "Ha", "Hunter", "Tom", "Lily", "Jay", "Jim", "Kuku", "Locu" };

                List<string> testList = new List<string>();

                testList.AddRange(temArr);

                if (testList.Contains("Hunter"))

                {

                    Console.WriteLine("There is Hunter in the list");

                }

                else

                {

                    testList.Add("Hunter");

                    Console.WriteLine("Add Hunter successfully.");

                }

    六.给List里面的元素排序:

    List.Sort();

    :mList.Sort();

    .List里面元素顺序反转:

      List. Reverse ()能够不List. Sort ()配合使用,达到想要的效果

      例:

      mList.Sort();

      八、List清空:

      List. Clear ()

      例:

      mList.Clear();

      九、获得List中元素数目:

      List. Count ()返回int

      例:

      in tcount = mList.Count();

      Console.WriteLine("The num of elements in the list: "+count);

    综合案例:

    using System;

    using System.Collections.Generic;

    using System.Linq;

    using System.Text;

    using System.Threading.Tasks;

    namespace 集合

    {

        class Program

        {

            static void Main(string[] args)

            {

                //比較List<T>(泛型的)ArrayList(非泛型的)

                People p1 = new People("zhangsan", 21);

                People p2 = new People("lisi", 11);

                People p3 = new People("wangwu", 41);

                //People对象加到集合中

                List<People> list = new List<People>(4);

                list.Add(p1);

                list.Add(p2);

                list.Add(p3);

                /*假设不指定list容量大小,默认是0,仅仅要有元素增加时,会自己主动扩展到4,假设第五个元素增加时

                 * 就变成了8,第九个元素增加时,就变成了16

                 * 能够看出,容量总是成倍的增长,扩展时要又一次开辟内存,这样会影响效率,假设事先知道元素个数,

                 * 或者可能推断个数,最好给出个大体的容量值

                 * 我们增加了三个元素,就设容量大小为4.注意:设为4不是说仅仅能存放四个元素

                 * 而是说,假设超出四个,一样会成倍扩展,这样做是为了减小扩展带来的开销             

                 */

                /*

                 * 这种方法作用是清楚多于的没实用的内存空间.比如:假设开辟大小为100

                 * 可是我们仅仅用了4,其余的不用,是不是浪费

                 * 本方法调用时会检查元素个数是不是占到了容量的90%以上

                 * 假设是,则不进行回收

                 */

                list.TrimExcess();

                /*ArrayList方法和List<T>使用方法一样,不同的是,它是对象集合

                 * 參数是object这样会有装箱拆箱的可能

                 * 所以尽量使用List<>           

                 */

                /*

                 * 1.初始化集合器

                 * C#3.0開始,提供了初始化功能,可是并没有反映到IList代码中

                 * IList,一样也是把它转化成Add方法调用              

                 */

                List<int> l2 = new List<int>() { 1, 2, 3, 4, 5 };

                /*

                 * 2.加入元素AddRange()方法能够一次性加入一批对象             

                 */

                List<People> lists = new List<People>(10);

                //參数是一个必须可能迭代的对象,也可能是一个数组

                list.AddRange(new People[] { new People("aladdin", 20), new People("zhao", 6) });

                //构造传入批量參数,AddRange效果一样

                List<People> myList = new List<People>(new People[] { new People("aladdin", 20), new People("zhao", 6) });

                /*

                 * 3.插入元素

                 * 使用Insert()方法,能够在指定位置插入元素

                 * 例 我们在1的位置插入,则最后变成了aladdin jacky zhao..插入意思就是,这个位我占了,

                 * 曾经占这位的和他之后的,通通往后移一位

                 */

                myList.Insert(1, new People("Jacky", 22));

                foreach (var p in myList)

                {

                    Console.WriteLine(p.name);

                }

                /*

                 *4.訪问元素

                 *ArrayListList<T>都是提供了索引器来訪问的

                 */

                Console.WriteLine("*********訪问元素********");

                for (int i = 0; i < myList.Count; i++)

                {

                    Console.WriteLine(myList[i].name);

                }

                //还能够使用foreach迭代器来实现

                /*

                 * public delegate void Action<T>(T obj);用托付作为參数

                 */

                Console.WriteLine("********foreach方法输出********");

                myList.ForEach(param => Console.WriteLine(param.name));

                /*

                 * 5.删除元素

                 * 删除元素能够使用RemoveAt()直接传入索引器值

                 * 将第一个元素直接删除

                 */

                myList.RemoveAt(0);

                List<People> lists2 = new List<People>(10);

                People per1 = new People("aladdin", 100);

                People per2 = new People("zhao", 100);

                People per3 = new People("jacky", 100);

                lists2.Add(per1);

                lists2.Add(per2);

                lists2.Add(per3);

                lists2.Remove(per3);

                Console.WriteLine("***********删除后的元素*********");

                foreach (var per in lists2)

                {

                    Console.WriteLine(per.name);

                }

                /*

                 * 从结果能够看出,名称为jacky的元素被删除了

                 * 以下说一下Remove方法的删除过程

                 * IndexOf方法确定出对象的索引,然后按索引删除

                 * IndexOf方法内,首先检查元素是不是实现了IEquatable接口,假设是,就调用这个

                 * 这个接口的Equals()方法

                 * 假设没有实现,则掉用Object中的Equals方法比較元素(也就是地址比較)

                 * 以上我们删除per3,非常明显是一个地址,所以被删除了

                 * 以下我们改装People,实现了IEquatable<People,

                 * 比較方法中,始终返回false,per3会比較失败,不会被删除

                 * 结果三个都在

                 * 假设要删除对象,最好使用索引直接删除,由于Remove方法经历了一系列过程后,最后才按索引删除!

                 * 

                 * RemoveRange()方法删除一个范围

                 * 第一个參数:開始位置;第二个參数:个数

                 * lists2.RemoveRange(1,2);

                 * 使用foreach查看批量删除后的结果

                 * foreach (var per in lists2)

                 *{

                 *   Console.WriteLine(per.name);

                 *}

                 * 

                 */

                /*

                 * 6.搜索

                 * 搜索有非常多方式,能够使用

                 * IndexOf,LastIndexOf,FindIndex,FindLastIndex,Find,FindLast

                 * 假设指示查看元素的存在情况,能够使用Exists()方法

                 * IndexOf()方法须要将一个对象做參数,假设存在,就返回本元素在集合中的索引,

                 * 假设找不到就返回-1,IndexOf还能够使用IEquatable接口来比較元素                                       

                 */

                List<People> ls3 = new List<People>(10);

                People person1 = new People("aladdin",100);

                People person2 = new People("zhao",100);

                People person3 = new People("jacky",100);

                ls3.Add(person1);

                ls3.Add(person2);

                ls3.Add(person3);

                //为了使用默认的地址比較,我们把People的接口临时去掉

                int index = ls3.IndexOf(person3);

                Console.WriteLine("per3的索引 : "+index);

                //还能够指定搜索范围 从第三个開始,范围长度为1

                int index2 = ls3.IndexOf(person3, 2, 1);

                Console.WriteLine(index2);

                //FindIndex()方法用来搜索带有一定特性的元素

                //用托付做參数 public delegate bool Predicate<T>(T obj);

                int index3 = ls3.FindIndex(param => param.name.Equals(""));

                Console.WriteLine(index3);//2

                //FindLastIndex是从 后面查第一个出现的元素,由于我们这里没有反复元素,所以

                //体现不出它仅仅能查找一个,就停下来的效果

                int index4 = ls3.FindLastIndex(p => p.name.Equals("aladdin"));

                Console.WriteLine(index4);

                //Find方法与FindIndex方法用于一样,不同的是,它返回的是元素本身

                People ppp = ls3.Find(p => p.name.Equals("jacky"));

                Console.WriteLine(ppp);

                /*

                 * 假设要查找全部的匹配元素,而不是找到第一个就停下来,就是用FindAll()方法

                 * 我们查找全部年纪等于100的对象,3个都符合

                 */

                List<People> newList = ls3.FindAll(p => p.age == 100);

                Console.WriteLine("**********查找全部**********");

                foreach (var p in newList)

                {

                    Console.WriteLine(p.name);

                }

                /*

                 * 7.排序

                 * List能够利用Sort方法排序,实现算符是高速排序

                 * 本方法有好几个重载

                 * public void Sort()仅仅对元素实现了IComparable才干使用这种方法 ,假设实现了则,能够直接调用一次sort之后,就排好序了

                 * public void Sort(Comparison<T> comparison)我们的Person并没有实现那个接口,所以要用泛型托付当參数的方法

                 * public void Sort(IComparer<T>(T x , T y))泛型接口当參数 public delegate int Comparison<T>(T x, T y);

                 * 

                 * public void Sort(int index ,int count ,IComparer<T> comparer) 能够指定范围

                 */

                List<People> ls4 = new List<People>(10);

                People person4 = new People("aladdin",100);

                People person5 = new People("zhao", 33);

                People person6 = new People("jacky", 44);

                ls4.Add(person4);

                ls4.Add(person5);

                ls4.Add(person6);

                ls4.Sort(MyComparFunc);

                Console.WriteLine("***********排序后的************");

                foreach (var p in ls4)

                {

                    Console.WriteLine(p.name+p.age);

                }

                Console.WriteLine("***********颠倒顺序***********");

                ls4.Reverse();

                foreach (var p in ls4)

                {

                    Console.WriteLine(p.name+p.age);

                }

                /*

                 * 8.类型转换  能够将集合中的元素转换成随意类型的元素,比方,

                 * 我们要将集合中的People转换成为Racer对象Racer仅仅包括名字,没有年纪

                 * public List<T Output>ConvertAll<TOutput>(Converter<T, TOutput> converter);

                 * public delegate T Output Converter<T Input, T Output>(T Input input);  托付參数

                 */

                List<Racer> ls5 = ls4.ConvertAll<Racer>((input) => new Racer(input.name));

                Console.WriteLine("***********转换后的玩意***********");

                foreach (var r in ls5)

                {

                    Console.WriteLine(r.name);

                }

                /*9.仅仅读集合

                 * 在创建完集合以后,肯定是可读的,假设不是,他就不能再加入新元素了

                 * 可是,假设是觉得填充完成,不要再做改动

                 * 能够使用仅仅读集合,使用AsReadOnly方法返回ReadOnlyCollection<T>

                 * 类型,它与List<>操作是一样的,可是一但有改动集合的操作,就会抛出异常

                 * 它屏蔽了通常的Add方法

                 */

                IReadOnlyCollection<Racer> persss = ls5.AsReadOnly();

                Console.WriteLine("输出仅仅读集合");

                foreach (var r in persss)

                {

                    Console.WriteLine(r.name);

                }

                Console.ReadKey();

            }

            public static int MyComparFunc(People p1, People p2)

            {

                if (p1.age==p2.age)

                {

                    return 0;

                }

                else if (p1.age > p2.age)

                {

                    return 1;

                }

                else

                {

                    return -1;

                }

            }

        }

        public class People

        {

            public string name;

            public int age;

            public People(string name, int age)

            {

                this.name = name;

                this.age = age;

            }

        }

        public class Racer

        {

            public string name;

            public Racer(string name)

            {

                this.name = name;

            }

        }

    }

    C#中数组,ArrayListList三者的差别

    C#中数组,ArrayList,List都可以存储一组对象,那么三者究竟有何差别呢?

    数组

    数组在C#中最早出现的.在内存中是连续存储的,所以他的索引速度非常快,并且赋值与改动元素也非常easy.

    案例:

    string [] s=new string [2];

    //赋值

    s[0]=”a”;

    s[1]=”b”;

    //改动

    s[1]=”aa”;

    可是数组存在一些不足的地方.在数组的两个数据间插入数据是非常麻烦的,并且在声明数组的时候必须制定数组的长度,数组的长度过长,会造成内存浪费,过界会造成数据溢出的错误.假设在声明数组的时候我们不清楚数组的长度,就会变得非常麻烦.

    针对数组的这些缺点,C#中最先提供了ArrayList对象来克服这些缺点.

    ArrayList

    ArrayList是命名空间System.Collections下的一部分,在使用该类时必须进行引用,同一时候继承了IList接口,提供了数据存储和检索.ArrayList对象的大小是依照当中存储的数据来动态扩充与收缩的.所以,在声明ArrayList对象时并不须要指定它的长度.

    案例:

    ArrayList  list1=new ArrayList();

    //新增数据

    list1.Add(“cde”);

    list1.Add(5678);

    //改动数据

    list1[2]=34;

    //移除数据

    list1.Remove(0);

    //插入数据

    list1.Insert(0,”qwe”);

    从上面样例看,ArrayList好像是攻克了数组中的全部的缺点,为什么又会有List?

    我们从上面的样例看,List,我们不仅插入了字符串cde,并且插入了数字5678.这样在ArrayList中插入不同类型的数据是同意的.由于ArrayList会把全部插入当中的数据当做为object类型来处理,在我们使用ArrayList处理数据时,非常可能会报类型不匹配的错误,也就是ArrayList不是类型安全的.在存储或检索值类型时通常发生装箱和拆箱操作,带来非常呆的性能损耗.

    装箱与拆箱的概念:

    简单的说:

    装箱:就是将值类型的数据打包到引用类型的实例中

    比方将string类型的值abc赋给object对象obj

    案例:

    string i=”abc”;

    object obj=(object)i;

    拆箱:就是从引用数据中提取值类型

    比方将object对象obj的值赋给string类型的变量i :

    object obj=”abc”;

    string i=(string)obj;

    装箱与拆箱的过程是非常损耗性能的.

    泛型List

    由于ArrayList存在不安全类型与装箱拆箱的缺点,所以出现了泛型的概念.List类是ArrayList类的泛型等效类,他的大部分使用方法都与ArrayList相似,由于List类也继承IList接口.最关键的却别在于,在声明List集合时,我们同事须要为其声明List集合内数据的对象类型.

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

    //新增数据

    list.Add(“abc”);

    //改动数据

    list[0]=”def”;

    //移除数据

    list.Remove(0);

    上例中,假设我们往List集合中插入int数组123,IDE就会报错,且不能通过编译.这样就避免了前面讲的类型安全问题与拆箱的性能问题了.

    总结:数组的容量是固定的,您仅仅能一次获取或设置一个元素的值,ArrayListList<T>的容量可依据须要自己主动扩充,改动,删除或插入数据.

    数组能够具有多个维度,ArrayListList<T>时钟仅仅具有一个维度.可是您能够轻松创建数组列表或列表的列表.特定类型(object除外)的数组的性能优于ArrayList的性能.这是由于ArrayList的元素属于object类型;所以在存储或检索值类型时通常发生装箱和拆箱操作.只是,在不须要又一次分配时(即最初的容量十分接近列表的最大容量),List<T>的性能与同类型的数组十分相近.

    在决定使用List<T>还是使用ArrayList(两者具有类似的功能),记住List<T>类在大多数情况下运行的更好而且是类型安全的.假设对List<T>类的类型T使用引用类型,则两个类的行为是全然同样的.可是,假设对类型T使用值类型,则须要考虑实现和装箱操作.

  • 相关阅读:
    mysql备份
    Linux 配置参考
    oracle补丁安装
    多智能体城市交通计算综合应用
    基于纳什均衡的多智能体强化学习交通信号控制
    多智能体强化学习在城市交通信号控制中的研究与应用- 笔记
    Sarsa与Q-learning
    Pandas笔记
    Python学习笔记
    Game Theory and Multi-agent Reinforcement Learning笔记 下
  • 原文地址:https://www.cnblogs.com/cxchanpin/p/6895383.html
Copyright © 2011-2022 走看看