C# 集合之 ArrayList

数组的长度声明后就是固定的,且都是存的同一种类型的数据。

集合的长度是不固定的(主要特征),可以存不同类型的元素;但泛型集合必须是同一种类型的集合

集合内部的原理用的还是数组,都是依赖于数组的,内部存数据都是存到了数组中。

集合的命名空间

  • using System.Collections;(非泛型集合)
  • using System.Collections.Generic;(泛型集合)

常用集合

  • 类似数组集合:AraylList、List<T>
  • “键值对”集合(“哈希表”集合):HashtableDictionary<K,V>
  • “堆栈”集合:StackStack<T>(LIFO)Last In First Out
  • “队列”集合:QueueQueue<T>(FIFO)First In First Out
  • “可排序键值对“集合:(插入、检索没有“哈希表”集合高效)
    • SortedlListSortedList<K, V>(占用内存更少,可以通过索引访词)
    • SortedDictionary<K,V>(占用内存更多,没有索引,但插入、删除元素的速度比SortedList快)
  • Set集合:无序、不重复。HashSet<T>,可以将HashSet类视为不包含值的Dictionary集合。与List<T>类似。SortedSet<T>(.net4.0支持,有序无重复集合)
  • “双向链表”集合:LinkedList<T>,增删速度快。

增删改查遍历

ArrayListHashtableList<T>Dictionary<K,V>

  • 数组的特点:类型统一长定固定
  • 集合常用操作添加、遍历、移除
  • 命名空间System.Colections
  • ArayList可变长度数组,使用类似于数组
    • 属性Capacity(集合中以容纳元素的个数,翻信增长);Count(集合中实际存放的元素的个数。)
    • 方法
      • Add(10) AddRange(ICollection c) Remove() RemoveAt() Clear()
      • Contains() ToArray() Sort() 排序 Reverse()//反转
  • Hashtable 键值对的集合,类似于字典,Hashtable在查找元素的时候,速度很快。
    • Add(object key, object value);
    • hash["key"];
    • hash["key"]="修改";
    • ContainsKey(key);
    • Remove("key");
    • 遍历;
    • hash.Keys;
    • hasth.Values/Dictionary Entry;
    • 键值对集合中的"键",绝对不能重复。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Collections;

namespace 集合
{
    static class Program
    {
        static void Main()
        {
            ArrayList arrayList = new ArrayList();// 注意提示有几个重载函数。
            //向集合中增加元素
            arrayList.Add(10); // 传的参数为 object,什么类型都可以。
            arrayList.Add("10");
            arrayList.Add("张三丰");
            Person gj = new Person() {
                Name = "郭靖",
            };
            arrayList.Add(gj); // 添加对象也可以。
            
            // ▼ Count 表示集合中的元素实际个数
            Console.WriteLine("集合中存在的元素个数{0}。", arrayList.Count);
            // ▼ Capacity 容量,可以理解:容量有 100,实际上可以只放 1 个元素。
            Console.WriteLine("集合现在的容量{0}", arrayList.Capacity);
            Console.WriteLine("==========传接口类型==========");
            // ICollection 接口, ArrayList 自己也可以往里传,数组也可以。所有集合,所有数组都可以传。
            // 实现了 ICollection 的类都可以
            arrayList.Add(new int[] { 1, 3, 5, 7, 9 });
            //  集合获取元素
            Console.WriteLine(arrayList[0]);// 用索引器访问
            Console.WriteLine(arrayList[3]);
            Console.WriteLine("==========for 循环遍历集合==========");
            // ▼ for 循环遍历集合
            for(int i = 0; i < arrayList.Count; i++) {
                // C# 所有集合长度都是 Count,数组都是 Length。
                Console.WriteLine(arrayList[i]);
            }
            // 向指定位置插入一个元素
            Console.WriteLine("==========向指定位置插入一个元素==========");
            arrayList.Insert(0, "洪七公");//  索引为 0 的位置中插入,以前的依次向后移动
            for (int i = 0; i < arrayList.Count; i++) {
                // C# 所有集合长度都是 Count,数组都是 Length。
                Console.WriteLine(arrayList[i]);
            }
            // 也可以插一堆的元素
            Console.WriteLine("==========向指定位置插入一堆元素==========");
            arrayList.InsertRange(3, new string[]{ "a", "good", "moring"});
            for (int i = 0; i < arrayList.Count; i++) {
                // C# 所有集合长度都是 Count,数组都是 Length。
                Console.WriteLine(arrayList[i]);
            }

            // 删除元素 可以根据 IDE 的提示参数去理解函数的含义
            //arrayList.Remove;
            //arrayList.RemoveAt;//  根据索引来删除
            //arrayList.RemoveRange;//  删除一段,从第几个开始删除到第几个元素,这个比较好理解。

            Console.WriteLine("===========删除结果是:=============");
            Console.WriteLine(arrayList.Count);
            for (int i = 0; i < arrayList.Count; i ++) {
                arrayList.RemoveAt(i);
            }
            Console.WriteLine(arrayList.Count);// 可见,删一个就移动重组一下。

            Console.WriteLine("===========清除ArrayList=============");
            arrayList.Clear();
            Console.WriteLine("集合中存在的元素个数{0}。", arrayList.Count);
            // foreach 是只读循环
            Console.WriteLine("===========根据对象来删除=============");
            // ▼ 根据对象来删除
            Person p1 = new Person() {
                Name = "雪山飞狐",
                Age = 100,
                Email = "nb@sina.com.cn"
            };

            arrayList.Add(p1);
            arrayList.Add(99);
            arrayList.Add("黄蓉");

            Person p2 = new Person() {
                Name = "雪山飞狐",
                Age = 100,
                Email = "nb@sina.com.cn"
            };
            arrayList.Add(p2);
            Console.WriteLine("集合中存在的元素个数{0}。", arrayList.Count);
            arrayList.Remove(99);
            Person p3 = new Person();
            p3.Name = "雪山飞狐";
            p3.Age = 100;
            p3.Email = "nb@sina.com.cn";
            Console.WriteLine("集合中存在的元素个数{0}。", arrayList.Count);
            arrayList.Remove(p3);// 这个对象没有添加,也就没有删除,但也没报错
            Console.WriteLine("集合中存在的元素个数{0}。", arrayList.Count);
            // 如果这样就能删掉
            p3 = p1;
            arrayList.Remove(p3);// 这个对象没有添加,也就没有删除,但也没报错
            Console.WriteLine("集合中存在的元素个数{0}。", arrayList.Count);
            // ▲ 这样能删除

            string name = new string(new char[] { '黄', '蓉'});
            arrayList.Remove(name);  // 删除掉了“黄蓉”
            Console.WriteLine("集合中存在的元素个数{0}。", arrayList.Count);

            // 总结:
            // Remove 并不是按照是不是对象的地址来删除的,而是判断是不是相等来删除的。

            Console.WriteLine(arrayList.Contains(99)); // 判断是否包含这个元素

        }
    }

    public class Person
    {
        public string Name {
            get;
            set;
        }
        public int Age {
            get;
            set;
        }
        public string Email {
            get;
            set;
        }
    }
}

输出:

集合中存在的元素个数4。
集合现在的容量4
==========传接口类型==========
10
集合.Person
==========for 循环遍历集合==========
10
10
张三丰
集合.Person
System.Int32[]
==========向指定位置插入一个元素==========
洪七公
10
10
张三丰
集合.Person
System.Int32[]
==========向指定位置插入一堆元素==========
洪七公
10
10
a
good
moring
张三丰
集合.Person
System.Int32[]
===========删除结果是:=============
9
4
===========清除ArrayList=============
集合中存在的元素个数0。
===========根据对象来删除=============
集合中存在的元素个数4。
集合中存在的元素个数3。
集合中存在的元素个数3。
集合中存在的元素个数2。
集合中存在的元素个数1。
False
请按任意键继续. . .

ArrayList 排序等

要想任意类型实现ArrayList Sort() 排序,需要实现 IComparable 这个接口。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Collections;

namespace ArrayList排序等
{
    static class Program
    {
        static void Main()
        {
            #region ArrayList 的 sort 方法
            ArrayList arr = new ArrayList(new int[] { 1, 3, 26, 9, 10 });
            Console.WriteLine("==========升序========");
            arr.Sort();// 注意有三个重载
            for (int i = 0; i < arr.Count; i++) {
                Console.WriteLine(arr[i]);
            } // 默认的是升序排序,从小到大.没有降序排序但可以 Reverse
            Console.WriteLine("==========降序========");
            arr.Reverse(); //  先升序,再反转就成降序了
            for (int i = 0; i < arr.Count; i++) {
                Console.WriteLine(arr[i]);
            }

            /*字符串排序*/
            ArrayList arrList = new ArrayList(new string[] { "hl", "xzl", "yzk", "fxh","ksjd","" ,"zaz"});
            arrList.Sort();
            Console.WriteLine("==========字符串排序========");
            for (int i = 0; i < arrList.Count; i++) {
                Console.WriteLine(arrList[i]);
            }
            // ▲ 字符串排序,按第一个字母 ASCII 码大小排序。第一个字母比完,第二个字母比,依次比较。
            //   升序比较。
            Console.WriteLine("==========对象排序========");
            ArrayList arrObj = new ArrayList();
            Person p1 = new Person() {
                Name = "hjk",
                Age = 100,
                Email = "hhh@andyvj.com"
            };
            Person p2 = new Person() {
                Name = "gdss",
                Age = 90,
                Email = "sd@andyvj.com"
            };
            Person p3 = new Person() {
                Name = "cbv",
                Age = 80,
                Email = "ge@andyvj.com"
            };
            Person p4 = new Person() {
                Name = "rtsssy",
                Age = 70,
                Email = "ghkj@andyvj.com"
            };
            arrObj.Add(p1);
            arrObj.Add(p2);
            arrObj.Add(p3);
            arrObj.Add(p4);
            Console.WriteLine("元素个数:" + arrObj.Count);
            arrObj.Sort(); // 对象不能直接按这个排,因为不知道按什么排
            // 对象需要继承 IComparable 接口实现 CompareTo方法
            for (int i = 0; i < arrObj.Count; i++) {
                Console.WriteLine(((Person)arrObj[i]).Name); // 装箱成对象了,要强制转一下。
            }
            // 想要 Sort 排序,数据类型必须是实现过 IComparable 这个接口的
            // 所以 Person 对象想要排序,就必须要实现 IComparable 这个接口
            #endregion
        }

        public class Person: IComparable         
        {
            public string Name {
                get;
                set;
            }
            public int Age {
                get;
                set;
            }
            public string Email {
                get;
                set;
            }

            // ▼ IComparable 接口实现 CompareTo方法
            public int CompareTo(object obj)
            {
                Person p = obj as Person;
                if (p != null) {
                    /*
                    return this.Age - p.Age;  // 升序降序在这里改下相减的前后顺序
                    //  ▲ 按照年龄,大 > 0,等 = 0, 小 < 0
                    */
                    return this.Name.Length - p.Name.Length; // 按名字的长度排序
                }

                return 0;
            }

            // 总结:要想任意类型实现ArrayList Sort() 排序,需要实现  IComparable 这个接口。
        }
    }
}

输出:

==========升序========
1
3
9
10
26
==========降序========
26
10
9
3
1
==========字符串排序========

fxh
hl
ksjd
xzl
yzk
zaz
==========对象排序========
元素个数:4
hjk
cbv
gdss
rtsssy
请按任意键继续. . .

ArrayList 任何情况排序

总结:如果要升序再写一个类实现 IComparer,如果按年龄再写一个类实现IComparer,依次… 有多少个情况。

就写多少个比较的类就行了,不用去改源代码。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Collections;

namespace Arralist随意排序
{
    static class Program
    {
        static void Main()
        {
            Console.WriteLine("==========对象排序========");
            ArrayList arrObj = new ArrayList();
            Person p1 = new Person() {
                Name = "hjk",
                Age = 100,
                Email = "hhh@andyvj.com"
            };
            Person p2 = new Person() {
                Name = "gdss",
                Age = 90,
                Email = "sd@andyvj.com"
            };
            Person p3 = new Person() {
                Name = "cbv",
                Age = 800,
                Email = "ge@andyvj.com"
            };
            Person p4 = new Person() {
                Name = "rtsssy",
                Age = 70,
                Email = "ghkj@andyvj.com"
            };
            arrObj.Add(p1);
            arrObj.Add(p2);
            arrObj.Add(p3);
            arrObj.Add(p4);
            Console.WriteLine("元素个数:" + arrObj.Count);

            // ▼ 直接调用Sort()方法是使用person类型实现了IComparab1e接口的默认方式来排序
            //  arrObj.Sort();
            for (int i = 0; i < arrObj.Count; i++) {
                Console.WriteLine(((Person)arrObj[i]).Age);
            }
            // 看 Sort() 函数的重载提示,有 IComparer 接口类型参数,一个比较器。
            // 所以有一个实现了接口的类就可以了。

            arrObj.Sort(new PersonSortByNameLengthAsc());
            Console.WriteLine("==========姓名长短排序后========");

            for (int i = 0; i < arrObj.Count; i++) {
                Console.WriteLine(((Person)arrObj[i]).Name);
            }
        }
    }

    public class Person: IComparable
    {
        public string Name {
            get;
            set;
        }
        public int Age {
            get;
            set;
        }
        public string Email {
            get;
            set;
        }

        public int CompareTo(object obj)
        {
            Person p = obj as Person;
            if (p != null) {
                return this.Age - p.Age;
            }

            return 0;
        }
    }

    // ▼ 这个类就是一个比较器
    public class PersonSortByNameLengthAsc : IComparer
    {
        public int Compare(object x, object y)
        {
            Person p1 = x as Person;
            Person p2 = y as Person;
            if (x != null && y != null) {
                return p1.Name.Length - p2.Name.Length;
            } else {
                throw new Exception("null 无法比较");
            }
        }
    }

    // 总结:如果要升序再写一个类实现 IComparer,如果按年龄再写一个类实现IComparer,依次… 有多少个情况
    // 就写多少个比较的类就行了,不用去改源代码了。
}

输出:

==========对象排序========
元素个数:4
100
90
800
70
==========姓名长短排序后========
hjk
cbv
gdss
rtsssy
请按任意键继续. . .



参考:
1.C# .Net基础加强第六天 // B站视频教程地址,来自:传智播客

上一篇:c# 数组自定义排序


下一篇:task的启动方式