C# 集合详解

现在各个集合类结合示例进行讲解:

一、泛型列表(List<T>)

1、声明语法及成员概要

 class Program
    {
        static void Main(string[] args)
        {
            var intList = new List<int>(10);           //创建特定类型的泛型列表
            Console.WriteLine("Capacity: {0}", intList.Capacity); //列表容量
            Console.WriteLine("Count: {0}", intList.Count);  // 列表元素个数
            intList.Capacity = 30;
            Console.WriteLine("Capacity: {0}", intList.Capacity);
            intList.TrimExcess(); //去除不需要的容量,但当元素达到容量90%时,TrimExcess()方法什么也不会做
            Console.WriteLine("Capacity: {0}", intList.Capacity);  
          

            //集合初始值设定项等同于调用列表的Add()方法
            var intList2 = new List<int>() { 1, 2 };  //集合初始值设定项只能在声明时使用
            intList2.Add(3);
            Console.WriteLine(intList2.Count);
            Console.ReadLine();
        }
    }

2、列表的具体操作详解

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ConsoleApp1
{
    class Program
    {
        static void Main(string[] args)
        {
            var hanmeimei = new Racer(2, "meimei", "han", "Brittain", 2);
            var lilei = new Racer(5, "lei", "li", "America", 4);
            var susan = new Racer(10, "leo", "susan", "Francio", 1);


            var racers = new List<Racer>(20) { hanmeimei, lilei, susan };
         

            racers.Add(new Racer(11, "le", "susa", "Francio", 3));
            racers.Add(new Racer(23, "re", "nfd", "Russia", 3));

            
            racers.AddRange(new Racer[] { new Racer(54, "ngsf", "an", "Brittain", 2) ,
                new Racer(65, "ngf", "tre", "Brittain", 2) }); // AddRange()方法的参数IEnumerable<T>对象,所以可以传递一个数组

            var racers1 = new List<Racer>(new Racer[] { new Racer(54, "ngsf", "an", "Brittain", 2) ,
                new Racer(65, "ngf", "tre", "Brittain", 2) });
            racers.Insert(3, new Racer(65, "ngf", "tre", "Brittain", 2)); //在制定位置插入元素

            //列表的访问
            var racer1 = racers[3];
            for (int i = 0; i < racers.Count; i++)
                Console.WriteLine(racers[i]);
            foreach (Racer r in racers)
                Console.WriteLine(r); //因为foreach 语句实现了IEnumerable接口
            racers.ForEach(Console.WriteLine);   // ForEach()将Action<T>作为参数, Console.WriteLine()方法的一个重载版本将object作为参数
            racers.ForEach(r => Console.WriteLine("{0:A}", r)); //同上  lambda表达式,优点:可以传递格式

            //删除(索引《更快》或者元素删除)
            racers.RemoveAt(2);
            if(!racers.Remove(hanmeimei)) //if(!racers.Remove(new Racer(5, "lei", "li", "America", 4)))因为Iequatable<T>和Object.equals()方法都没在racer类中重写,所以不能用要删除元素相同内容创建一个新对象,再把它传递给remove()方法
                Console.WriteLine("Object can not found!");
            racers.RemoveRange(2, 4);//参数1-索引, 参数2-元素个数
            //查看元素是否存在,List<T>类提供了exist()方法;
            racers.Exists(r => r.FirstName == "meimei");
            //搜索
            racers.IndexOf(hanmeimei);  //找到返回索引,没找到返回-1
            // 搜索指定特性的元素
           int index = racers.FindIndex(r => r.Country == "America");
            Racer r1 = racers.Find(r => r.FirstName == "NiKi");
            Racer r2 = racers.FindLast(r => r.FirstName == "NiKi");  // 查找与Predicate<T>类型匹配的最后一项

            //查找与Predicate<T>类型匹配的所有项
            List<Racer> bigWinners = racers.FindAll(r => r.Wins > 3);
            foreach (Racer r in bigWinners)
                Console.WriteLine("{0:A}", r);
           

            //排序
            racers.Sort();  //可以不带参数,因为racer实现了IComparable<T>接口
            Console.ReadLine();
            racers.ForEach(Console.WriteLine);

            racers.Sort(new RacerComparer(RacerComparer.CompareType.FirstName)); // RacerComparer已经实现了IComparer<T>接口
            Console.ReadLine();
            racers.ForEach(Console.WriteLine);

            racers.Sort((x, y) => x.Wins.CompareTo(y.Wins));   //  Comparison<T>是一个委托。注: public void List<T>.Sort(Comparison<T>).
            Console.ReadLine();
            racers.ForEach(Console.WriteLine);
            racers.ForEach(r => Console.WriteLine("{0:A}", r)); //同上  lambda表达式
            Console.ReadLine();

            //逆转整个集合顺序
            racers.Reverse();
            racers.ForEach(r => Console.WriteLine("{0:A}", r)); //lambda表达式

            // 类型转换
            // ConvertAll<TOutput>() 方法使用一个converter委托,该委托定义如下
            // public sealed delegate TOutput Converter<TInput, TOutput>(TInput from);
            racers.ConvertAll<Person>(r => new Person(r.FirstName+ " " + r.LastName ));

       //只读集合

          

using System;
using System.Collections.Generic;

public class Example
{
    public static void Main()
    {
        List<string> dinosaurs = new List<string>(4);

        Console.WriteLine("\nCapacity: {0}", dinosaurs.Capacity);

        dinosaurs.Add("Tyrannosaurus");
        dinosaurs.Add("Amargasaurus");
        dinosaurs.Add("Mamenchisaurus");
        dinosaurs.Add("Deinonychus");

        Console.WriteLine();
        foreach(string s in dinosaurs)
        {
            Console.WriteLine(s);
        }

        Console.WriteLine("\nIList<string> roDinosaurs = dinosaurs.AsReadOnly()");
        IList<string> roDinosaurs = dinosaurs.AsReadOnly();

        Console.WriteLine("\nElements in the read-only IList:");
        foreach(string dinosaur in roDinosaurs)
        {
            Console.WriteLine(dinosaur);
        }

        Console.WriteLine("\ndinosaurs[2] = \"Coelophysis\"");
        dinosaurs[2] = "Coelophysis";

        Console.WriteLine("\nElements in the read-only IList:");
        foreach(string dinosaur in roDinosaurs)
        {
            Console.WriteLine(dinosaur);
        }
    }
}

            Console.ReadLine();
        }
    }

    public class Racer : IComparable<Racer>, IFormattable
    {
        public Racer(int id, string firstName, string lastName, string country)
            : this(id, firstName, lastName, country, 0)
        { }
        public Racer(int id, string firstName, string lastName, string country, int wins)
        {
            this.ID = id;
            this.FirstName = firstName;
            this.LastName = lastName;
            this.Country = country;
            this.Wins = wins;
        }
        public int ID { get; private set; }
        public string FirstName { get; set; }
        public string LastName { get; set; }
        public string Country { get; set; }
        public int Wins { get; set; }

        public override string ToString()
        {
            return string.Format("{0} {1}", FirstName, LastName);
        }
        public string ToString(string format, IFormatProvider formatProvider)
        {
            if (format == null)
                return ToString();
            switch (format.ToUpper())
            {
                case "N":
                    return ToString();
                case "F":
                    return FirstName;
                case "L":
                    return LastName;
                case "C":
                    return string.Format("{0}, Country: {1}", ToString(), Country);
                case "W":
                    return  string.Format("{0}, Wins: {1}", ToString(), Wins);
                case "A":
                    return string.Format("{0} {1} Wins: {2}", ToString(), ID, Wins);
                default:
                    throw new FormatException(string.Format(formatProvider, "Format {} is not supported!", format));

            }
        }
        public string Tostring(string format)
        {
            return ToString(format, null);
        }
        public int CompareTo(Racer other)
        {
            if (other == null) return -1;
            int compare = string.Compare(this.LastName, other.LastName);
            if (compare == 0)
                compare = string.Compare(this.FirstName, other.FirstName);
            return compare;
        }
    }
    public class RacerComparer : IComparer<Racer>
    {
        public enum CompareType
        {
            FirstName,
            LastName,
            Country,
            Wins
        }
        private CompareType compareType;
        public RacerComparer(CompareType compareType)
        {
            this.compareType = compareType;
        }
        public int Compare(Racer x, Racer y)
        {
            if (x == null && y == null) return 0;
            if (x == null) return -1;
            if (y == null) return 1;
            int result;
            switch (compareType)
            {
                case CompareType.FirstName:
                    return string.Compare(x.FirstName, y.FirstName);
                case CompareType.LastName:
                    return string.Compare(x.LastName, y.LastName);
                case CompareType.Country:
                    result = string.Compare(x.Country, y.Country);
                    if (result == 0)
                        return string.Compare(x.LastName, y.LastName);
                    return result;
                case CompareType.Wins:
                    return x.Wins.CompareTo(y.Wins);
                default:
                    throw new ArgumentException("Invalid CompareType");

            }
        }
    }

    public class Person
    {
        public string name;
        public Person(string name)
        {
            this.name = name;
        }
        public override string ToString()
        {
            return name;
        }
    }
}

二、队列

using System.Threading;
namespace Wrox
{
    class Program
    {
        static void Main()
        {
            var dm = new DocumentManager();
            ProcessDocument.Start(dm);

            for (int i = 0; i < 1000; i++)
            {
                var doc = new Document("Doc." + i.ToString(), "content");
                dm.AddDocument(doc);
                Console.WriteLine("Add document: {0}", doc.Title);
                Thread.Sleep(new Random().Next(20));
            }

            Console.ReadLine();
        }

    }
    public class Document
    {
        public string Title { get; private set; }
        public string Content { get; private set; }
        public Document(string title, string content)
        {
            this.Title = title;
            this.Content = content;
        }
    }
    public class DocumentManager
    {
        private readonly Queue<Document> doucumentQueue = new Queue<Document>();
        public void AddDocument(Document doc)
        {
            lock(this)
            {
                doucumentQueue.Enqueue(doc);
            }
        }
        public Document GetDocument()
        {
            Document doc = null;
            lock (this)
            {
                 doc = doucumentQueue.Dequeue();
            }
            return doc;
        }
        public bool IsDocumentAvainable
        {
            get {

                return doucumentQueue.Count > 0;
            }
        }
    }
    public class ProcessDocument
    {
        public static void Start(DocumentManager dm)
        {
            Task.Factory.StartNew(new ProcessDocument(dm).Run);  // Task类表示一个异步操作
        }
        public ProcessDocument(DocumentManager dm)
        {
            if (dm == null)
                throw new ArgumentException("dm");
            documentManager = dm;
        }
       private DocumentManager documentManager;
        protected void Run()
        {
            while (true)
            {
                if (documentManager.IsDocumentAvainable)
                {
                    Document doc = documentManager.GetDocument();
                    Console.WriteLine("Processing Document: {0}", doc.Title);
                }

            }
            Thread.Sleep(new Random().Next(20));  //将线程挂起随机出现的不大于20毫秒的毫秒数。 Thread类创建和控制线程,设置其优先级并获取其状态。
        }                                          // Random类表示伪随机数生成器,这是一种能够产生满足某些随机性统计要求的数字序列的设备。
    }
}

三、栈

namespace chapter10
{
    class Program
    {
        static void Main()
        {
            var alphabet = new Stack<char>();
            alphabet.Push('A');
            alphabet.Push('B');
            alphabet.Push('C');

            Console.WriteLine("Firsst iteration:");
            foreach (var item in alphabet)
            {
                Console.WriteLine(item);
            }
            Console.WriteLine("Second iteration:");
            while (alphabet.Count > 0)
            {
                Console.WriteLine(alphabet.Pop());  // peek()获取栈顶元素但不删除元素,contains()确定某个元素是否在栈中,是则返回true;
            }
            Console.ReadLine();
        }

    }
}

四、链表(以文档按优先级添加为示例)

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Text.RegularExpressions;

namespace chapter10
{
    class Program
    {
        static void Main()
        {
            var pdm = new PriorityDocumentmanager();
            pdm.AddDocument(new Document("1", "sample", 8));
            pdm.AddDocument(new Document("1", "sample", 3));
            pdm.AddDocument(new Document("1", "sample", 4));
            pdm.AddDocument(new Document("1", "sample", 8));
            pdm.AddDocument(new Document("1", "sample", 1));
            pdm.AddDocument(new Document("1", "sample", 9));
            pdm.AddDocument(new Document("1", "sample", 1));
            pdm.AddDocument(new Document("1", "sample", 1));

            pdm.DisplayAllNodes();
            Console.ReadLine();
        }

    }

    public class Document
    {
        public string Title { get; private set; }
        public string Content { get; private set; }
        public byte Priority { get; private set; }
        public Document(string title, string content, byte priority)
        {
            this.Title = title;
            this.Content = content;
            this.Priority = priority;
        }
    }

    public class PriorityDocumentmanager
    {
        private readonly LinkedList<Document> documentList;   //注意双向链表文档按优先级排列的顺序和优先级节点的取值
        private readonly List<LinkedListNode<Document>> priorityNodes;

        public PriorityDocumentmanager()
        {
            documentList = new LinkedList<Document>() ;
            priorityNodes = new List<LinkedListNode<Document>>(10);
            for (int i = 0; i < 10; i++)
            {
                priorityNodes.Add(new LinkedListNode<Document>(null));
            }
        }
        public void AddDocument(Document d)
        {
            if (d == null) throw new ArgumentNullException("d");
            AddDocumentToPriorityNode(d, d.Priority);
        }
        private void AddDocumentToPriorityNode(Document d, int priority)
        {
            //优先级入口检测
            if (priority > 9 || priority < 0)
                throw new ArgumentException("Priority must between 0 and 9!");
            //是否存在与文档优先级相同的节点
            if (priorityNodes[priority].Value == null)  
            {
                --priority; 
                if (priority >= 0)
                {
                    AddDocumentToPriorityNode(d, priority); //递归,直至找到比文档优先级低的文档或者优先级超过优先级超过下限
                }
                else                          //优先级超过优先级超过下限
                {
                    documentList.AddLast(d);                      
                    priorityNodes[d.Priority] = documentList.Last;
                }
                return;
            }
            else  //a priority node exists
            {
                LinkedListNode<Document> prioNode = priorityNodes[priority];
                if (d.Priority == priority)  //存在与文档优先级相同的节点
                {
                    documentList.AddAfter(prioNode, d);
                    priorityNodes[d.Priority] = prioNode.Next;
                }
                else  //存在比文档优先级低的节点
                {
                    LinkedListNode<Document> firstPrioNode = prioNode;
                    //循环,直至找到同等优先级的第一项(因为在链表中各优先级项首尾相连)
                    while (firstPrioNode.Previous != null && firstPrioNode.Previous.Value.Priority == prioNode.Value.Priority)
                    {
                        firstPrioNode = prioNode.Previous;
                        prioNode = firstPrioNode;
                    }
                    documentList.AddBefore(firstPrioNode, d);
                    priorityNodes[d.Priority] = firstPrioNode.Previous;
                }
            }
        }

        public void DisplayAllNodes()
        {
            foreach (var dc in documentList)
            {
                Console.WriteLine("Priority: {0}, Title: {1}", dc.Priority, dc.Title);
            }
        }

        //return rhe document with the highest priority and delete it

        public Document GetDocument()
        {
            Document dc = documentList.First.Value;
            documentList.RemoveFirst();  // RemoveLast()方法删除链表最后一项
            return dc;    
        }
    }
}   // 特别注意,链表中,优先级不同的按照优先级排序,优先级相同的按进入链表的时间先后顺序排序,不同且相邻优先级相关项首尾相连
五、有序列表(按照键给元素排序)

namespace chapter10
{
    class Programm
    {
        static void Main()
        {
            var books = new SortedList<string, string>();  //有序列表  sortedList<TKey, TValue> 键和值可以使用任意类型
            books.Add("fdafdsaf", "4234254");
            books.Add("rewr", "42323543");
            books["fasdrwaer"] = "423543";   //索引把键作为参数
            books["hasdewr"] = "7657653";

            foreach (KeyValuePair<string, string> s in books)  //枚举器的返回类型为KeyValuePair<TKey, TValue>
            {
                Console.WriteLine("Key: {0}, Value: {0}", s.Key, s.Value); //通过key, value属性来访问
            }
            foreach (string s in books.Keys)  //通过Keys属性来访问键
            {
                Console.WriteLine(s);
            }
            foreach (string s in books.Values)  //通过Values属性来访问值
            {
                Console.WriteLine(s);
            }

            // 访问(也可用索引器直接访问,但如果不存在,会抛出异常)
            string s1 = "fasfas";
            string s2;
            //避免访问异常的方法
            if (!books.TryGetValue(s1, out s2)) //尝试获取指定键的值。 如果使用 ContainsKey()方法,所传递的键在值中,返回true。
            {
                Console.WriteLine("Title: {0} is not founded", s1);
            }
            Console.ReadLine();
        }
    }
}
六、字典

using  System.Diagnostics.Contracts;
namespace Chapter10
{

    class Program
    {
        public static void Main()
        {
            var employees = new Dictionary<EmployeeId, Employee>();
            var s1 = new EmployeeId("c323");
            var s2 = new Employee("fdfd", 42342.00m, s1);
            employees.Add(s1, s2);
            var s3 =new EmployeeId("F424");
            var s4 = new Employee("fsdaf", 5353.00m, s3);
            employees[s3] = s4;
            while(true)
            {
                Console.WriteLine("Enter emplyee Id:");
                var userInput = Console.ReadLine();
                userInput = userInput.ToUpper();
                if (userInput == "X") break;
                EmployeeId id;
                try
                {
                    id = new EmployeeId(userInput);
                    Employee employee;
                    if (!employees.TryGetValue(id, out employee))
                    {
                        Console.WriteLine("Employee with {0} does not exist!", id);
                    }
                    else
                        Console.WriteLine(employee);
                }
                catch (EmployeeIdException e)
                {
                    Console.WriteLine(e.Message);
                }
            }
        }
    }
    public class EmployeeIdException : Exception
    {
        public EmployeeIdException(string message) : base(message){} 
    }
    public struct EmployeeId:  IEquatable<EmployeeId>
    {
        private readonly char prefix;
        private readonly int number;
        public EmployeeId(string id)
        {
           
            prefix = (id.ToUpper())[0];
            int numberLength = id.Length - 1;
            try
            {
                number = int.Parse(id.Substring(1, numberLength));
            }
            catch (FormatException)
            {
                throw new EmployeeIdException("Invalid EmployeeId format!");
            }
        }
        public override string ToString()
        {
            return prefix.ToString() + string.Format("{0, 6:000000}", number);
        }
        public override int GetHashCode()
        {
            return  (number ^ number << 16) * 0x15051505;
        }
        public bool Equals(EmployeeId other)
        {
            if (other == null)
                return false;
            return (prefix == other.prefix && number == other.number);
        }
        public override bool Equals(object obj)
        {
            return Equals((EmployeeId) obj);
        }
        public static bool operator ==(EmployeeId left, EmployeeId right)
        {
            return left.Equals(right);
        }
        public static bool operator !=(EmployeeId left, EmployeeId right)
        {
            return !(left == right);
        }
    }
    public class Employee
    {
        private string name;
        private decimal salary;
        private readonly EmployeeId id;

        public Employee(string name, decimal salary, EmployeeId id)
        {
            this.name = name;
            this.salary = salary;
            this.id = id;
        }
        public override string ToString()
        {
            return string.Format("{0}: {1, -20} {2:C}", id.ToString(), name, salary);
        }
    }
}
//lookUp类

  var lookUpRacers = racers.ToLookup(r => r.Country);   //ToLookup()是一个扩展方法,它用于任何实现了枚举接口的类
            foreach (var r in lookUpRacers["Francio"])
                Console.Write(r);

// 集合

namespace Chapter10
{
    class Programm
    {
        public static void Main()
        {
            var companyTeams = new HashSet<string>() { "122", "123", "234" };
            var traditionalTeams = new HashSet<string> () { "122", "123" };
            var privateTeams = new HashSet<string>() { "222", "223", "543", "4234", "534" };

            if (companyTeams.Add("432")) //添加项
                Console.WriteLine("432 added");
            if (!traditionalTeams.Add("123"))  //该项已经存在
                Console.WriteLine("123 was already in this set");
            if (traditionalTeams.IsSubsetOf(companyTeams))// 子集
                Console.WriteLine("traditionalTeams Is Subset  Of companyTeams");
            if (companyTeams.IsSupersetOf(traditionalTeams))//超集
                Console.WriteLine("companyTeams Is Superset Of traditionalTeams");
            traditionalTeams.Add("543");
            if (traditionalTeams.Overlaps(privateTeams)) //交集
                Console.WriteLine("At leat one item is the same with the  traditionalTeams and privateTeams");

            //用unionwith()方法合集

            var AllTeams = new SortedSet<string>(companyTeams);
            AllTeams.UnionWith(traditionalTeams);
            AllTeams.UnionWith(privateTeams);
            Console.WriteLine("\nAll teams:");
            foreach (var s in AllTeams)
                Console.WriteLine(s);

            //用exceptWith()方法集中删除Allteams中的所有私有队
            AllTeams.ExceptWith(privateTeams);
            Console.WriteLine("\nAll teams:");
            foreach (var s in AllTeams)
                Console.WriteLine(s);  //字符串都是按序输出


            Console.Read();
        }
    }
}

//可观察的集合
using System.Collections.ObjectModel;
using System.Collections.Specialized;
namespace Chapter10
{
    class program
    {
        public static void Main()
        {
            var data = new ObservableCollection<string>();
            data.CollectionChanged += Data_CollectionChanged; //为事件注册方法
            data.Add("One");
            data.Add("two");
            data.Insert(1, "Three");
            data.Remove("Three");
            Console.Read();

            void Data_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
            {
                Console.WriteLine("Action: {0}", e.Action.ToString());  //获取该事件的操作
                if (e.OldItems != null)
                {
                    Console.WriteLine("Starting index for old items: {0}", e.OldStartingIndex);
                    Console.WriteLine("Ole item(s): ");
                    foreach (var item in e.OldItems)
                        Console.WriteLine(item);
                }
                if (e.NewItems != null)
                {
                    Console.WriteLine("Starting index for new items: {0}", e.NewStartingIndex);
                    Console.WriteLine("New item(s): ");
                    foreach (var item in e.NewItems)
                        Console.WriteLine(item);
                }
                Console.WriteLine();
            }
        }
    }
}

tips:

1.可以通过索引访问的集合类:ArrayList、StringCollection、List<T>

猜你喜欢

转载自blog.csdn.net/qq_39885625/article/details/81231714