Analyze the C # Set internally -- List & lt; T & gt ;,

Source: Internet
Author: User

Analyze the C # Set internally -- List <T>,

Let's discuss some of the mechanisms of C # list <T> today. If there is anything wrong with it, please feel grateful even if you spend it ..

List <T> Introduction

1. List <T> is a non-thread-safe set.

When I look at the List <T> source code, I find the SynchronizedList class. From this name and its code implementation, it is a thread-safe set, but it is unclear how the SynchronizedList and List <T> work together to implement thread security, or is this method only used for the FCL class library? Anyone who knows this can be confused ..

[Serializable ()] internal class SynchronizedList: IList <T> {private MyList <T> _ list; private Object _ root; internal SynchronizedList (MyList <T> list) {_ list = list; _ root = (System. collections. ICollection) list ). syncRoot;} public int Count {get {lock (_ root) {return _ list. count ;}} public bool IsReadOnly {get {return (ICollection <T>) _ list ). isReadOnly ;}} public void Add (T item) {lock (_ root) {_ list. add (item) ;}} public void Clear () {lock (_ root) {_ list. clear () ;}} public bool Contains (T item) {lock (_ root) {return _ list. contains (item) ;}} public void CopyTo (T [] array, int arrayIndex) {lock (_ root) {_ list. copyTo (array, arrayIndex) ;}} public bool Remove (T item) {lock (_ root) {return _ list. remove (item) ;}} System. collections. IEnumerator System. collections. IEnumerable. getEnumerator () {lock (_ root) {return _ list. getEnumerator () ;}} IEnumerator <T> IEnumerable <T>. getEnumerator () {lock (_ root) {return (IEnumerable <T>) _ list ). getEnumerator () ;}} public T this [int index] {get {lock (_ root) {return _ list [index] ;}} set {lock (_ root) {_ list [index] = value ;}} public int IndexOf (T item) {lock (_ root) {return _ list. indexOf (item) ;}} public void Insert (int index, T item) {lock (_ root) {_ list. insert (index, item) ;}} public void RemoveAt (int index) {lock (_ root) {_ list. removeAt (index );}}}View Code

 

2. List <T> the internal data structure is relatively simple. The hash algorithm is used without hashtable or Dictionary. The default internal array length is 4 and the maximum length is 2146435071, list <T> does not have a load factor similar to Hashtable. It can also be understood that the load factor of List <T> is 1. When the add method is executed, you must determine whether the current list capacity is equal to the used capacity. If the list capacity is equal, you can scale up. The scaling rule is to double the current capacity.

3. The elements added to the list are ordered, and there is an internal _ size variable. Each time the add operation is executed, _ size plus one.

 

2. Performance Comparison Between List <T> and Dictionary.

Although their comparability was not too strong, it is still commonly used to add, search, and delete methods to make a comparison.

1) Add new elements

Theoretically, the ADD () of List <T> is faster than that of Dictionary, because List <T> does not have hash computing. This is also true in actual experiments.

Static void Main (string [] args) {for (int I = 0; I <10; I ++) {List <int> myList = new List <int> (); dictionary <int, int> myDict = new Dictionary <int, int> (); Stopwatch swatch = new Stopwatch (); swatch. restart (); for (int j = 0; j <100000; j ++) {myList. add (j);} swatch. stop (); Console. writeLine ("myList:" + swatch. elapsedTicks); swatch. restart (); for (int j = 0; j <100000; j ++) {myDict. add (j, j);} swatch. stop (); Console. writeLine ("myDict:" + swatch. elapsedTicks); Console. writeLine ("------------------------------");} Console. readKey ();}View Code

 

Execution result:

 

It can be seen that List <T> is an order of magnitude faster than Dictionary.

 

2) Search for elements

The query speed of a Dictionary is much faster than that of a list. In extreme cases, the query speed is several orders of magnitude,

Through the previous article, we know that Dictionary calculates the hash value of the key first, and then performs index locating through the hash value. list is a for loop first, and then compares it with the input expression value, the following code:

Public T Find (Predicate <T> match) {if (match = null) {ThrowHelper. throwArgumentNullException (ExceptionArgument. match);} Contract. endContractBlock (); for (int I = 0; I <_ size; I ++) {if (match (_ items [I]) {return _ items [I] ;}} return default (T );}View Code

 

Next we will test the performance comparison in two extreme cases:

Scenario 1:

Static void Main (string [] args) {for (int I = 0; I <10; I ++) {List <int> myList = new List <int> (); dictionary <int, int> myDict = new Dictionary <int, int> (); Stopwatch swatch = new Stopwatch (); for (int j = 0; j <10000000; j ++) {myList. add (j);} swatch. start (); var myListResult = myList. find (p => {return p = 9999999;}); swatch. stop (); Console. writeLine ("myList:" + swatch. elapsedTicks); for (int j = 0; j <10000000; j ++) {myDict. add (j, j);} swatch = new Stopwatch (); swatch. start (); var myDictResult = myDict [9999999]; swatch. stop (); Console. writeLine ("myDict:" + swatch. elapsedTicks); Console. writeLine ("------------------------------");} Console. readKey ();}View Code

 

Result:

 

Scenario 2:

Static void Main (string [] args) {for (int I = 0; I <10; I ++) {List <int> myList = new List <int> (); dictionary <int, int> myDict = new Dictionary <int, int> (); Stopwatch swatch = new Stopwatch (); for (int j = 0; j <10000000; j ++) {myList. add (j);} swatch. start (); var myListResult = myList. find (p => {return p = 0;}); swatch. stop (); Console. writeLine ("myList:" + swatch. elapsedTicks); for (int j = 0; j <10000000; j ++) {myDict. add (j, j);} swatch = new Stopwatch (); swatch. start (); var myDictResult = myDict [0]; swatch. stop (); Console. writeLine ("myDict:" + swatch. elapsedTicks); Console. writeLine ("------------------------------");} Console. readKey ();}View Code

Result:

 

In the second extreme case, List <T> is faster than Dictionary. In combination with the previous article, I think you already know the reason,

 

 

3) remove elements

The Remove Method of List <T> calculates the index value of the element before removing the element, and then transmits the index value to the RemoveAt method to Remove the element. Therefore, we can see that when removing an element, it is also a List of all the items that have been replaced by a Dictionary <T>. If you do not need to talk about anything else, go to the source code directly.

Static void Main (string [] args) {for (int I = 0; I <10; I ++) {MyList <int> myList = new MyList <int> (); dictionary <int, int> myDict = new Dictionary <int, int> (); Stopwatch swatch = new Stopwatch (); for (int j = 0; j <10000000; j ++) {myList. add (j);} swatch. start (); myList. remove (55555); swatch. stop (); Console. writeLine ("myList:" + swatch. elapsedTicks); for (int j = 0; j <10000000; j ++) {myDict. add (j, j);} swatch = new Stopwatch (); swatch. start (); var myDictResult = myDict. remove (55555); swatch. stop (); Console. writeLine ("myDict:" + swatch. elapsedTicks); Console. writeLine ("------------------------------");} Console. readKey ();}View Code

Running result:

 

I personally think that the most fundamental reason for their performance difference in element insertion and deletion is that the hash used by Dictionary does not exist in the List, even if the hash computing of Dictionary has a certain performance loss, the overall performance is still complete.

The next section describes the implementation of ArrayList. In fact, ArrayList and list are more comparable.

 

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.