zoukankan      html  css  js  c++  java
  • C#集合之列表

      .NET Framework为动态列表List提供泛型类List<T>。这个类实现了IList,ICollection,IEnumerable,IList<T>,ICollection<T>,IEnumerable<T>接口。
    1.创建列表
      创建一个赛车手类,下面的例子会用到:

       public class Racer : IComparable<Racer>, IFormattable
          {
            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 Racer(int id, string firstName, string lastName, string country)
              : this(id, firstName, lastName, country, wins: 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 override string ToString()
            {
              return String.Format("{0} {1}", FirstName, LastName);
            }
    
            public string ToString(string format, IFormatProvider formatProvider)
            {
              if (format == null) format = "N";
              switch (format.ToUpper())
              {
                case null:
                case "N": // name
                  return ToString();
                case "F": // first name
                  return FirstName;
                case "L": // last name
                  return LastName;
                case "W": // Wins
                  return String.Format("{0}, Wins: {1}", ToString(), Wins);
                case "C": // Country
                  return String.Format("{0}, Country: {1}", ToString(), Country);
                case "A": // All
                  return String.Format("{0}, {1} Wins: {2}", ToString(), Country, Wins);
                default:
                  throw new FormatException(String.Format(formatProvider,
                        "Format {0} 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)
                return string.Compare(this.FirstName, other.FirstName);
              return compare;
            }
          }

      调用默认的构造函数,就可以创建列表对象。在List<T>中,必须为声明为列表的值指定类型:
      var intList = new List<int>();
      var racers =new List<Racer>();
      使用默认的构造函数创建一个空列表。元素添加到列表中后,列表的容量就会扩大为可接纳4个元素。如果添加到第五个元素,列表的大小就会重新设置为包含8个元素。如果8个元素还不够,列表的大小就会重新设置为包含16个元素。每次都会将列表容量重新设置为原来的2倍。
      如果列表的容量改变了,整个集合就会重新分配到一个新的内存块中。在List<T>泛型类的实现代码中,使用了一个T类型的数组。通过重新分配内存,创建一个新数组,Array.Copy()方法将旧数组中的元素复制到新数组中。为节省时间,如果事先知道列表中的元素个数,就可以用构造函数定义其容量:
      List<int> intList = new List<int>(10);
      使用Capacity属性可以获取和设置集合的容量:
      intList.Capacity = 20;
      集合的元素个数用Count属性读取。

      如果已经将元素添加到列表中,且不希望添加的更多的元素,就可以调用TrimExcess()方法,去除不需要的容量。但是,因为重新定位需要时间,所以如果元素的个数超过了容量的90%,该方法就什么也不做。
      intList.TrimExcess();

      还可以使用集合初始值给集合赋值:
      var intList = new List<int>(){1,2};
      集合初始值并没有反映在已编译的程序集的IL代码中,编译器会把集合初始值变成对初始值列表中的每一项调用Add()方法。

    2.添加元素
      使用Add()方法可以给列表添加元素:
      intList.Add(1);
      intList.Add(2);

      使用AddRange()方法,可以一次给集合添加多个元素。因为AddRange()方法的参数是IEnumerable<T>类型的对象,所以可以传递一个数组:
      intList.AddRange(
        new Int[]{1,2}
      );
      如果在实例化列表时知道集合的元素个数,就亦可以将实现IEnumerable<T>类型的对象传递给类的构造函数,类似AddRange()方法:
      var intList = new List<int>(
        new Int[]{1,2}
      );

    3.插入元素
      使用Insert()方法可以在指定位置插入元素:
      intList.Insert(3,4);
      方法InsertRange()可以插入大量的元素。
      racers.InsertRange(3, new Racer[] {
        new Racer(12, "Jochen", "Rindt", "Austria", 6),
        new Racer(22, "Ayrton", "Senna", "Brazil", 41) });

    4.访问元素
      实现了IList和IList<T>接口的所有类都提供了一个索引器,可以使用索引器来访问元素:
      int i = intList[0;]
      String类也可以通过索引访问字符:
      string s = "sdas";
      char c = s[0];

      因为List<T>集合类实现了IEnumerable接口,所以也可以使用foreach(http://www.cnblogs.com/afei-24/p/6738155.html)语句遍历集合中的元素:
      foreach(int i in intList)
      {
        //..
      }
      除了使用foreach语句之外,List<T>类还提供了ForEach()方法,该方法用Action<T>参数声明:
      public void ForEach(Action<T> action);
      .NEt实现ForEach()方法的代码如下:
      public class List<T>:ILIst<T>
      {
        private T[] items;

        //...

        public void ForEach(Action<T> action)
        {
          if(action==null) throw new ArgumentNullException("action");

          foreach(T item in items)
          {
            action(item);
          }
        }
      }

      实例:
      racers.ForEach(
        r =>
        {
          Console.WriteLine(r.ToString())
        }
      );
      这里使用了lambda表达式(http://www.cnblogs.com/afei-24/p/6795233.html)。

    5.删除元素
      删除元素时,可以利用索引,也可以传递要删除的元素:
      var graham = new Racer(7, "Graham", "Hill", "UK", 14);
      var emerson = new Racer(13, "Emerson", "Fittipaldi", "Brazil", 14);
      var mario = new Racer(16, "Mario", "Andretti", "USA", 12);
      var racers = new List<Racer>(20) { graham, emerson, mario };
      racers.RemoveAt(3);
      racers.Remove(graham);

      按索引删除比较快,因为必须在集合中搜索要删除的元素。Remove方法先在集合中搜索,用IndexOf方法获取元素的索引,再使用该索引删除元素。IndexOf方法先检查元素类型是否实现了IEquatable<T>接口。如果是,就调用这个接口的Equals()方法,确定集合中的元素是否等于传递给Equals()方法的元素。如果没有实现这个接口,就使用Object类的Equals()方法比较这些元素。Object类的Equals()方法默认实现代码对值类型进行按位比较,对引用类型只比较其引用。

      RemoveRange()方法可以从集合中删除许多元素。它的第一个参数指定了开始删除的元素索引,第二个参数指定了要删除的元素个数:
      int index = 3;
      int count = 5;
      racers.RemoveRange(index,count);
      要删除集合中的所有元素,可以使用ICollection<T>接口定义的Clear()方法:
      racers.Clear();
      RemoveAll()方法删除有指定特性的所以元素。这个方法使用Predicate<T>类型的参数定义。下面将介绍Predicate<T>类型。

    6.搜索
      获得要查找的元素的索引,或者搜索元素的本身。可以使用的方法有IndexOf(),LastIndexOf(),FindIndex(),FindLastIndex(),Find(),FindLast().
      如果只检查元素是否存在,可以使用Exists()方法。

      IndexOf()方法需要将一个对象作为参数,如果在集合中找到该元素,这个方法就返回该元素的索引。如果没有找到就返回—1.IndexOf方法使用IEquatable<T>接口来比较元素。
      使用IndexOf()方法,还可以指定不需要搜索整个集合,指定从哪个元素开始搜索以及搜索几个元素。

      除了使用IndexOf()方法搜索指定元素之外,还可以搜索有某个特性的元素,该特性可以用FindIndex(),FindLastIndex(),Find(),FindLast()方法来定义,这些方法需要一个Predicate<T>类型的参数:
      如:
      public int FindIndex(Predicate<T> match);
      Predicate<T>类型是一个委托:public delegate bool Predicate<T>(T obj);
      其用法和Foreach()方法的Action委托类似。如果Predicate<T>委托返回true,就表示有一个匹配元素。如果返回false,表示没找到,继续搜素。
      FindIndex(),FindLastIndex()方法返回找到的匹配元素的一个索引;Find(),FindLast()返回这个匹配的元素。

      如果要获得与Predicate<T>匹配的所有项而不是一项,可以使用FindAll()方法。FindAll()方法的用法一样。FindAll()方法找到第一项后不会停止,而是继续迭代集合中的每一项:
      List<Racer> l = racers.FindAll(r => r.Wins > 20);

    7.排序
      List<T>类可以使用Sort()方法对集合中的元素排序。Sort()方法使用快排算法排序。
      Sort()方法有多个重载的方法。可以传递泛型委托Comparison<T>和泛型接口IComparer<T>,以及一个范围值和泛型接口IComparer<T>:
      public void List<T>.Sort();
      public void List<T>.Sort(Comparison<T>);
      public void List<T>.Sort(IComparer<T>);
      public void List<T>.Sort(Int32,Int32,IComparer<T>);
      只有集合中的元素实现了IComparable接口,才能使用不带参数的Sort()方法。

      使用public void List<T>.Sort(IComparer<T>); 需要定义一个实现了IComparer<T>接口的类,调用Sort(IComparer<T>)方法时会调用实现了IComparer<T>接口的类中的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);
                      else
                        return result;
                    case CompareType.Wins:
                      return x.Wins.CompareTo(y.Wins);
                    default:
                      throw new ArgumentException("Invalid Compare Type");
                  }
                }
              }

        客户端代码:
        racers.Sort(new RacerComparer(RacerComparer.CompareType.Country));

      使用public void List<T>.Sort(Comparison<T>); 需要一个Comparison<T>委托。Comparison<T>委托:public delagate int Comparsion<T>(int x,int y);
        客户端代码:
        racers.Sort((r1,r2) => r2.Wins.CompareTo(r1.Wins));


      使用Reverse()方法,可以逆转整个集合的顺序。

    8.类型转换
      使用List<T>类的ConvertAll<TOutput>()方法,可以把所以类型的集合转换位另一种类型。ConvertAll<TOutput>()方法使用Converte委托,Converte委托:public sealed delegate TOutput Converter<TInput,TOutput>(TInput from);

    //定义一个Person类
            public class Person
            {
                private string name;
                
                public Person(string name)
                {
                    this.name = name;
                }
                
                public override string ToString()
                {
                    return name;
                }
            }

    客户端代码:
      List<Person> persons =
      racers.ConvertAll<Person>(
        r => new Person(r.FiastName+" " + r.LastName)
      );

    9.只读集合
      创建集合后,它们就是可读写的。但是,在填充集合后,可以使用AsReadOnly()方法创建只读集合。
      List<Racer> racers2 =racers.AsReadOnly();

  • 相关阅读:
    curl crt
    test with nmap
    C#查询XML解决“需要命名空间管理器”问题
    Dapper实用教程
    javascript 计算两个日期的差值
    Glib学习笔记(二)
    安装osquery笔记
    Golang多线程简单斗地主
    PHP扩展开发之Zephir
    zabbix 安装记录
  • 原文地址:https://www.cnblogs.com/afei-24/p/6824791.html
Copyright © 2011-2022 走看看