zoukankan      html  css  js  c++  java
  • 14.集合

    1.System.Collections命名空间中的几个接口

    1)IEnumerable可迭代集合中的项;

    2)ICollection(继承于IEnumerable)可以获取集合中项的个数,并把项复制到一个简单的数组中;

    3)IList(继承于IEnumerable和ICollection)提供了集合的项列表,允许访问这些项,并提供一些与项相关的基本功能;

    4)IDictionary(继承于IEnumerable和ICollection)类似IList,但提供了通过键值(而不是索引)访问项的列表;

    以上几个接口提供了基本的集合功能。System.Array类实现了IEnumerable、ICollection和IList接口,但不支持IList的一些更高级的功能,它表示大小固定的项列表。C#中的数组是System.Array类的实例。

    2.使用数组实现扑克牌集合

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    
    namespace ConsoleApplication1
    {
        class Program
        {
            static void Main(string[] args)
            {
                Deck d = new Deck();
                for (int i = 0; i < 52; i++)
                {
                    Console.Write(d.GetCard(i));
                    
                }
                Console.WriteLine();
                Console.WriteLine();
                d.Shuffle();
    
                for (int i = 0; i < 52; i++)
                {
                    Console.Write(d.GetCard(i));
                    
                }
                d.GetCard(53);
                Console.WriteLine();
                Console.WriteLine();
                    Console.ReadLine();
            }
        }
    
       
    
        class Card
        {
            private readonly Suit suit;
            private readonly Rank rank;
    
            public Card(Suit suit,Rank rank)
            {
                this.suit = suit;
                this.rank = rank;
            }
    
            public override string ToString()
            {
                return "The "+rank .ToString()+" of "+ suit.ToString()+" s";
            }
        }
    
        /// <summary>
        /// 使用数组实现集合Deck,缺点是集合的大小是固定的
        /// </summary>
        class Deck {
            private Card[] Cars;
    
            public Deck()
            {
                Cars = new Card[52];
                for (int suitVal = 0; suitVal < 4; suitVal++)
                {
                    for (int rankVal = 1; rankVal <= 13; rankVal++)
                    {
                        Cars[suitVal * 13 + rankVal - 1] = new Card((Suit)suitVal, (Rank)rankVal);
                    }
                }
            }
    
            public Card GetCard(int cardNum)
            {
                if (cardNum >= 0 && cardNum <= 51)
                    return Cars[cardNum];
                else
                    throw new ArgumentOutOfRangeException("cardNum", cardNum, "Value must between 0 and 51.");
            }
    
            public void Shuffle()
            {
                Random sourceGen = new Random();
                Card[] newCards = new Card[52];
                bool[] assigned = new bool[52];
                for (int i = 0; i < 52; i++)
                {
                    int destCard = 0;
                    bool foundCard = false;
                    while (!foundCard)
                    {
                        destCard = sourceGen.Next(52);
                        if (assigned[destCard] == false)
                            foundCard = true;
                    }
                    assigned[destCard] = true;
                    Cars[destCard]=newCards[i];
                }
                newCards.CopyTo(Cars ,0);
            }
    
    
        }
    
        public enum Suit
        { 
            Club,//梅花
            Diamond,//方块
            Heart,//红桃
            Spade//黑桃
    
        }
    
        public enum Rank
        { 
            Ace=1,//幺点
            Deuce,//两点
            Three,
            Four,
            Fine,
            Six,
            Seven,
            Eight,
            Nine,
            Ten,
            Jack,
            Queen,
            King
    
        }
    }
    View Code

    数组实现集合的缺点:集合大小是固定的,不能改变。

    3.使用System.Collections.ArrayList实现扑克牌集合

    ArrayList也实现了IEnumerable、ICollection和IList接口,但比System.Array更复杂,和System.Array相比,它的大小是不固定的。

     abstract class Animal
        {
            protected string name;
            public string Name
            {
                get { return name; }
                set { name = value; }
            }
    
            public Animal()
            {
                name = "The animal has no name.";
            }
    
            public Animal(string newName)
            {
                name = newName;
            }
    
            public void Feed()
            {
                Console.WriteLine("{0}has been fed.", name);
            }
        }
    
        class Cow : Animal
        {
            public void Milk()
            {
                Console.WriteLine("{0}has been milked.", name);
            }
    
            public Cow(string newName)
                : base(newName)
            {
    
            }
        }
    
        class Chicken : Animal {
            public void LagEgg()
            {
                Console.WriteLine("{0}has lag en egg.", name);
            }
    
            public Chicken(string newName)
                : base(newName)
            { 
                
            }
        }
    View Code
    class Program
        {
    
            static void Main(string[] args)
            {
                Animal[] animalArray = new Animal[2];
                Cow myCow1 = new Cow("Deirdre");
                animalArray[0] = myCow1;
                animalArray[1] = new Chicken("Ken");
    
                foreach (Animal myAnimal in animalArray)
                {
                    Console.WriteLine("New {0} object added to collection,Name= {1}",myAnimal.ToString(),myAnimal.Name);
                }
    
                Console.WriteLine("Array collection contains {0} objects", animalArray.Length);
    
                animalArray[0].Feed();
                ((Chicken)animalArray[1]).LagEgg();
    
                ArrayList animalArrayList = new ArrayList();
                Cow myCow2 = new Cow("Hayley");
                animalArrayList.Add(myCow2);
                animalArrayList.Add(new Chicken("Roy"));
    
                foreach (Animal myAnimal in animalArrayList)
                {
                    Console.WriteLine("New {0} object added to ArrayList collection,Name = {1}", myAnimal.ToString(), myAnimal.Name);
                }
                Console.WriteLine("ArrayList collection contains {0} objects", animalArrayList.Count);
    
                ((Animal)animalArrayList[0]).Feed();
                ((Chicken)(animalArrayList[1])).LagEgg();
    
                animalArrayList.RemoveAt(0);
                animalArrayList.AddRange(animalArray);//后加入的排在前面
                ((Cow)animalArrayList[0]).Milk();
    
                Console.WriteLine("The animal called {0} is at index {1}", myCow1.Name, animalArrayList.IndexOf(myCow1));
                myCow1.Name = "Janice";
                Console.WriteLine("The animal is now called {0}", ((Animal)animalArrayList[0]).Name);
    
                Console.ReadLine();
            }
           
        }
    View Code

    数组和ArrayList的比较:

    数组需要用固定大小的常量值来初始化,初始化后大小是固定的,ArrayList有两个构造函数,另一个构造函数可以设置列变的初始大小,如果集合的项个数超过了这个值就增加一倍。ArrayList的大小是变化的。

    Animal[] animalArray = new Animal[2];
    
    ArrayList animalArrayList = new ArrayList();

    数组初始化之后,它的项并没有初始化,需要按照下标给每项分别初始化。ArrayList不能像数组那样初始化,因为他的项还没有添加,需要用Add方法才会添加一个新项,并为这个新项分配内存空间。

                Cow myCow1 = new Cow("Deirdre");
                animalArray[0] = myCow1;
                animalArray[1] = new Chicken("Ken");    
    
                Cow myCow2 = new Cow("Hayley");
                animalArrayList.Add(myCow2);
                animalArrayList.Add(new Chicken("Roy"));

    数组个数使用Length属性,ArrayList使用Count属性

    数组是强类型集合,ArrayList是System.Object的集合,使用时需要把对象强制转换为对应的类型

                animalArray[0].Feed();
                ((Chicken)animalArray[1]).LagEgg();
    
                ((Animal)animalArrayList[0]).Feed();
                ((Chicken)(animalArrayList[1])).LagEgg();

    ArrayList功能更多,比如RemoveAt,Remove,还可以使用AddRange方法把支持ICollection接口的对象加到集合中

    4.使用CollectionBase建立集合

    定制集合可以创建强类型化的集合,可以完全自己写代码创建集合,也可以通过继承现有类创建集合,一般通过继承集合底层的类创建集合。

    CollectionBase类实现了IEnumerable、ICollection和IList接口,但是只提供了一些实现代码,比如IList的Clear()和RemoveAt,以及ICollection的Count属性,需要用到其他功能需要自己实现。

    abstract class Animal
        {
            protected string name;
            public string Name
            {
                get { return name; }
                set { name = value; }
            }
    
            public Animal()
            {
                name = "The animal has no name.";
            }
    
            public Animal(string newName)
            {
                name = newName;
            }
    
            public void Feed()
            {
                Console.WriteLine("{0}has been fed.", name);
            }
        }
    
    class Animals : CollectionBase
        { 
            public void Add(Animal newAnimal)
            {
                List.Add(newAnimal);
            }
    
            public void Remove(Animal oldAnimal)
            {
                List.Remove(oldAnimal);
            }
    
            /// <summary>
            /// 索引符只能访问已添加的项,超过Count-1会产生超出索引异常
            /// </summary>
            /// <param name="animalIndex"></param>
            /// <returns></returns>
            public Animal this[int animalIndex]
            {
                get { return (Animal)List[animalIndex]; }
                set { List[animalIndex] = value; }
            }
        }
    View Code
        class Program
        {
    
            static void Main(string[] args)
            {
                Animals animalCollection = new Animals();
                Cow myCow1 = new Cow("Deirdre");
                animalCollection.Add(myCow1);
                animalCollection.Add(new Chicken("Ken"));
    
                foreach (Animal myAnimal in animalCollection)
                {
                    Console.WriteLine("New {0} object added to collection,Name= {1}",myAnimal.ToString(),myAnimal.Name);
                }
    
                Console.WriteLine(animalCollection[1].Name);
                Console.ReadLine();
            }
           
        }

    5.使用DictionaryBase创建集合

    DictionaryBase可以创建键值对集合,通过关键字访问项。DictionaryBase实现了IDictionary,IEnumerable、ICollection接口。和CollectionBase一样它提供了部分功能,如Clear()、和Count,但没有RemoveAt()因为它是IList接口上的功能,但是IDictionary接口有Remove功能,可以使用这个实现Remove功能。

    abstract class Animal
        {
            protected string name;
            public string Name
            {
                get { return name; }
                set { name = value; }
            }
    
            public Animal()
            {
                name = "The animal has no name.";
            }
    
            public Animal(string newName)
            {
                name = newName;
            }
    
            public void Feed()
            {
                Console.WriteLine("{0}has been fed.", name);
            }
        }
    
        class Animals :DictionaryBase
        { 
            public void Add(string newId, Animal newAnimal)
            {
                Dictionary.Add(newId, newAnimal);
            }
    
            public void Remove(string oldId,Animal oldAnimal)
            {
                Dictionary.Remove(oldId);
            }
    
            /// <summary>
            /// 索引符只能访问已添加的项,超过Count-1会产生超出索引异常
            /// </summary>
            /// <param name="animalIndex"></param>
            /// <returns></returns>
            public Animal this[string key]
            {
                get { return (Animal)Dictionary[key]; }
                set { Dictionary[key] = value; }
            }
        }
    
        class Program
        {
    
            static void Main(string[] args)
            {
                Animals animalCollection = new Animals();
                Cow myCow1 = new Cow("Deirdre");
                animalCollection.Add("111",myCow1);
                animalCollection.Add("222",new Chicken("Ken"));
    
                foreach (DictionaryEntry d in animalCollection)
                {
                    Console.WriteLine("New {0} object added to collection,Name= {1}",d.Value.ToString(),((Animal)d.Value).Name);
                }
                Console.WriteLine(animalCollection["111"].Name);
                Console.ReadLine();
            }
           
        }
    View Code

    6.迭代器

    我们知道IEnumerable接口是负责实现foreach循环的,假如循环的方式并不是我们想要的就需要重写循环方式,但是重写循环方式并不是很简单。我们看下在foreach循环中究竟干了什么。

    在foreach循环中,迭代集合collectionObject的过程如下:

    1)调用collectionObject.GetEnumerator(),返回一个IEnumerator引用。这个可以从IEnumerable接口的实现代码获取,但这是可选的,可以在实现IEnumerable接口的情况下创建一个GetEnumerator()用于循环(即下面说的迭代器);

    2)调用IEnumerator的MoveNext方法;

    3)如果MoveNext方法返回true,调用IEnumerator的Current获取对象的一个引用,用于foreach循环;

    4)重复上面两步直到循环结束。

    由此可以看出重写foreach循环方式需要重写几个方法(GetEnumerator(),MoveNext()等),跟踪索引,维护Current属性,以及执行其他一些操作,这需要做很多工作。比较简单的替代方法是使用迭代器。使用迭代器可以有效的在后台生成许多代码,不用我们去实现那么多。

    迭代器是一个代码块,它按顺序提供了要在foreach循环中用到的值

        class Program
        {
    
            static void Main(string[] args)
            {
                foreach(string s in SimpleList())
                {
                    Console.WriteLine(s);
                }
                Console.ReadLine();
            }
    
            static IEnumerable SimpleList()
            {
                yield return "string 1";
                yield return "string 2";
                yield return "string 3";
            }
           
        }

    以上是一个迭代器的例子,在迭代器中使用yield关键字提供在foreach循环中用到的值。迭代器的返回类型有IEnumerable和IEnumerator两种类型,这两个类型使用的场合是:

    1)如果要迭代一个类可以使用GetEnumerator方法,其返回类型是IEnumerator;

    2) 如果要迭代一个类成员,比如一个方法,使用IEnumerable。

    使用迭代器重写Animals foreach循环

    abstract class Animal
        {
            protected string name;
            public string Name
            {
                get { return name; }
                set { name = value; }
            }
    
            public Animal()
            {
                name = "The animal has no name.";
            }
    
            public Animal(string newName)
            {
                name = newName;
            }
    
            public void Feed()
            {
                Console.WriteLine("{0}has been fed.", name);
            }
        }
    
        class Cow : Animal
        {
            public void Milk()
            {
                Console.WriteLine("{0}has been milked.", name);
            }
    
            public Cow(string newName)
                : base(newName)
            {
    
            }
        }
    
        class Chicken : Animal {
            public void LagEgg()
            {
                Console.WriteLine("{0}has lag en egg.", name);
            }
    
            public Chicken(string newName)
                : base(newName)
            { 
                
            }
        }
    
        class Animals :DictionaryBase
        { 
            public void Add(string newId, Animal newAnimal)
            {
                Dictionary.Add(newId, newAnimal);
            }
    
            public void Remove(string oldId,Animal oldAnimal)
            {
                Dictionary.Remove(oldId);
            }
    
            /// <summary>
            /// 索引符只能访问已添加的项,超过Count-1会产生超出索引异常
            /// </summary>
            /// <param name="animalIndex"></param>
            /// <returns></returns>
            public Animal this[string key]
            {
                get { return (Animal)Dictionary[key]; }
                set { Dictionary[key] = value; }
            }
    
            public new IEnumerator GetEnumerator()
            {
                foreach (DictionaryEntry d in Dictionary)
                {
                    yield return (Animal)d.Value;
                }
            }
    
        class Program
        {
    
            static void Main(string[] args)
            {
                Animals animals = new Animals();
                animals.Add("111", new Cow("myCow1"));
                animals.Add("222", new Chicken("myChicken1"));
    
                foreach (Animal a in animals)
                {
                    a.Feed();
                }
                Console.ReadLine();
            }
        }
    View Code

    属性块用做迭代器

    class People:DictionaryBase
        {
            public void Add(string name, Person p)
            {
                this.Dictionary.Add(name, p);
            }
    
            public void Remove(string name)
            {
                this.Dictionary.Remove(name);
            }
    
            public Person this[string name]
            {
                get { return (Person)this.Dictionary[name]; }
                set { this.Dictionary[name] = value; }
            }
    
            public new IEnumerator GetEnumerator()
            {
                foreach (object d in Dictionary.Values)
                {
                    yield return (Person)d;
                }
    
            }
    
            public IEnumerable Ages
            {
                get {
                    foreach (object d in Dictionary.Values)
                    {
                        yield return ((Person)d).Age;
                    }
                }
            }
       
        }
    
        public class Person:IComparable
        {
            public string Name { get; set; }
            public int Age { get; set; }
    
            [System.Xml.Serialization.XmlElementAttribute("Books")]
            public Books Books { get; set; }
    
    
            public Person(string name, int age)
            {
                Name = name;
                Age = age;
            }
    
            public int CompareTo(object obj)
            {
                return this.Age-((Person)obj).Age;
            }
        }
  • 相关阅读:
    1036 商务旅行
    4165 ​高精度求阶乘
    3117 高精度练习之乘法
    封装代理
    freemarker写select组件(三)
    VC双缓冲画图技术介绍
    JS学习十七天----工厂方法模式
    Struts2 全局结果集
    HDU 1730 Northcott Game
    C++ STL:vector
  • 原文地址:https://www.cnblogs.com/lidaying5/p/10539570.html
Copyright © 2011-2022 走看看