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#中最早出现的.在内存中是连续存储的,所以他的索引速度非常快,而且赋值与修改元素也很简单.

    案例:

    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使用值类型,则需要考虑实现和装箱操作.

     

  • 相关阅读:
    android 中文 api (43) —— Chronometer
    SVN客户端清除密码
    Android 中文 API (35) —— ImageSwitcher
    Android 中文API (46) —— SimpleAdapter
    Android 中文 API (28) —— CheckedTextView
    Android 中文 API (36) —— Toast
    Android 中文 API (29) —— CompoundButton
    android 中文 API (41) —— RatingBar.OnRatingBarChangeListener
    Android 中文 API (30) —— CompoundButton.OnCheckedChangeListener
    Android 中文 API (24) —— MultiAutoCompleteTextView.CommaTokenizer
  • 原文地址:https://www.cnblogs.com/android-blogs/p/6603819.html
Copyright © 2011-2022 走看看