C#集合之列表

来源:http://www.cnblogs.com/afei-24/archive/2017/05/08/6824791.html
-Advertisement-
Play Games

.NET Framework為動態列表List提供泛型類List<T>。這個類實現了IList,ICollection,IEnumerable,IList<T>,ICollection<T>,IEnumerable<T>介面。1.創建列表 創建一個賽車手類,下麵的例子會用到: 調用預設的構造函數,就 ...


  .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();


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • linux tcp GSO和TSO實現 ——lvyilong316 (註:kernel版本:linux 2.6.32) 概念 TSO(TCP Segmentation Offload): 是一種利用網卡來對大數據包進行自動分段,降低CPU負載的技術。 其主要是延遲分段。 GSO(Generic Se ...
  • 參考博客: http://www.cnblogs.com/chensiqiqi/p/6243549.html 感謝原博主為我學習Linux指明方向!! linux目錄:一切從“根”開始,“/”是所有目錄的起點(定點) linux每個目錄可以掛載在不同的設備(磁碟)上。 在邏輯上所有目錄(包括目錄下的 ...
  • FastDFS架構簡介 FastDFS是一款開源的、分散式文件系統(Distributed File System),由淘寶開發平臺部資深架構師餘慶開發。FastDFS 是包括一組 Tracker Server 和 Storage Server 的。Tracker Server 與 Storage ...
  • 環境 Qemu: 2.8.0 開發板:vexpress-ca9 概述 前面的博文已經使我們的虛擬開發板具備了訪問外網的目的,離物聯網越來越近了。要玩物聯網,Yeelink不得不說,它提供了雲平臺,可以將設備的數據上傳到雲端,也可以聯網獲得雲端的數據,我們可以通過手機客戶端或在網頁端查看或修改,從而達 ...
  • Linux常用命令 使用PHP伺服器端腳本編程語言進行網站開發,需要在lamp環境下進行,Linux作為”四劍客”之一是有必要瞭解熟悉的,而Linux系統並不像windows操作系統那樣,以圖形化的界面展示給我們,我們只需要滑鼠鍵盤配合使用即可完成我們的需要. 因此Linux系統的特殊性使我們有必要 ...
  • find命令:用於在文件樹中查找文件,並作出相應的處理 1、find命令的格式; find pathname -options [-print -exec -ok ...] {}\ 2、find命令的參數; pathname: find命令所查找的目錄路徑。例如用“.”來表示當前目錄,用“/”來表示 ...
  • 功能說明:設置指令別名 語法:alias[別名]=[指令名稱] 詳解:1)不加參數,顯示已有的別名列表 2)設置別名:alias NAME='VALUE',使用NAME時相當於執行VALUE的內容 特別事項:1)定義的別名指針對當前Shell有效 2)要永久有效,需要定義配置文件 當前用戶:~/.b ...
  • 數組(http://www.cnblogs.com/afei-24/p/6738128.html)的大小是固定的。如果元素的個數是動態的,就應使用集合類。 列表(http://www.cnblogs.com/afei-24/p/6824791.html) 隊列(待寫) 棧(待寫) 鏈表(待寫) 有序 ...
一周排行
    -Advertisement-
    Play Games
  • 前言 本文介紹一款使用 C# 與 WPF 開發的音頻播放器,其界面簡潔大方,操作體驗流暢。該播放器支持多種音頻格式(如 MP4、WMA、OGG、FLAC 等),並具備標記、實時歌詞顯示等功能。 另外,還支持換膚及多語言(中英文)切換。核心音頻處理採用 FFmpeg 組件,獲得了廣泛認可,目前 Git ...
  • OAuth2.0授權驗證-gitee授權碼模式 本文主要介紹如何筆者自己是如何使用gitee提供的OAuth2.0協議完成授權驗證並登錄到自己的系統,完整模式如圖 1、創建應用 打開gitee個人中心->第三方應用->創建應用 創建應用後在我的應用界面,查看已創建應用的Client ID和Clien ...
  • 解決了這個問題:《winForm下,fastReport.net 從.net framework 升級到.net5遇到的錯誤“Operation is not supported on this platform.”》 本文內容轉載自:https://www.fcnsoft.com/Home/Sho ...
  • 國內文章 WPF 從裸 Win 32 的 WM_Pointer 消息獲取觸摸點繪製筆跡 https://www.cnblogs.com/lindexi/p/18390983 本文將告訴大家如何在 WPF 裡面,接收裸 Win 32 的 WM_Pointer 消息,從消息裡面獲取觸摸點信息,使用觸摸點 ...
  • 前言 給大家推薦一個專為新零售快消行業打造了一套高效的進銷存管理系統。 系統不僅具備強大的庫存管理功能,還集成了高性能的輕量級 POS 解決方案,確保頁面載入速度極快,提供良好的用戶體驗。 項目介紹 Dorisoy.POS 是一款基於 .NET 7 和 Angular 4 開發的新零售快消進銷存管理 ...
  • ABP CLI常用的代碼分享 一、確保環境配置正確 安裝.NET CLI: ABP CLI是基於.NET Core或.NET 5/6/7等更高版本構建的,因此首先需要在你的開發環境中安裝.NET CLI。這可以通過訪問Microsoft官網下載並安裝相應版本的.NET SDK來實現。 安裝ABP ...
  • 問題 問題是這樣的:第三方的webapi,需要先調用登陸介面獲取Cookie,訪問其它介面時攜帶Cookie信息。 但使用HttpClient類調用登陸介面,返回的Headers中沒有找到Cookie信息。 分析 首先,使用Postman測試該登陸介面,正常返回Cookie信息,說明是HttpCli ...
  • 國內文章 關於.NET在中國為什麼工資低的分析 https://www.cnblogs.com/thinkingmore/p/18406244 .NET在中國開發者的薪資偏低,主要因市場需求、技術棧選擇和企業文化等因素所致。歷史上,.NET曾因微軟的閉源策略發展受限,儘管後來推出了跨平臺的.NET ...
  • 在WPF開發應用中,動畫不僅可以引起用戶的註意與興趣,而且還使軟體更加便於使用。前面幾篇文章講解了畫筆(Brush),形狀(Shape),幾何圖形(Geometry),變換(Transform)等相關內容,今天繼續講解動畫相關內容和知識點,僅供學習分享使用,如有不足之處,還請指正。 ...
  • 什麼是委托? 委托可以說是把一個方法代入另一個方法執行,相當於指向函數的指針;事件就相當於保存委托的數組; 1.實例化委托的方式: 方式1:通過new創建實例: public delegate void ShowDelegate(); 或者 public delegate string ShowDe ...