C # collection dictionary,

Source: Internet
Author: User

C # collection dictionary,

A dictionary represents a complex data structure that allows elements to be accessed by a key. A dictionary is also called a ing or hash list.
The main feature of the dictionary is to quickly search for values based on keys. You can also freely add and delete elements, which is a bit like List <T> (http://www.cnblogs.com/afei-24/p/6824791.html), but there is no performance overhead for moving subsequent elements in memory.
Is a simplified representation, the key will be converted into a hash. Create a number using the hash, which associates the index and value. Then the index contains a link to the value. An index can be associated with multiple values, and an index can be stored as a tree structure.
  
. NET Framework provides several dictionary classes. The main class is Dictionary <TKey, TValue>.

1. Key type
The type used as the key in the dictionary must override the GetHashCode () method of the Object class. As long as the dictionary class needs to determine the position of the element, it must call the GetHashCode () method. The int returned by the GetHashCode () method has a dictionary used to calculate the index where elements are placed. This algorithm is introduced later. Now you only need to know that it involves a prime number, so the dictionary capacity is a prime number.
The implementation code of the GetHashCode () method must meet the following requirements:
* The same object always returns the same value.
* Different objects can return the same value.
* It should be executed quickly, with little computing overhead
* It cannot throw an exception
* It should use at least one instance Field
* Hash code values should be evenly distributed to the numerical range that can be stored by int.
* It is recommended that the hashed Code remain unchanged during the lifetime of the object.
The dictionary performance depends on the implementation code of the GetHashCode () method.

The reason why the hash code value should be evenly distributed to the numerical range that the int can store:
If the hash code values returned by the two keys get the same index, the dictionary class must find the nearest available free location to store the second data item, which requires a certain search, this item can be retrieved later. Obviously, this will reduce the performance. If many keys have the same index during sorting, this conflict is more likely to occur. According to Microsoft's algorithm, this risk is minimized when the calculated hash code value is evenly distributed between int. MinValue and int. MaxValue.

In addition to the GetHashCode () method, the key type must also implement the IEquatable <T>. Equals () method, or override the Object. Equals () method. 0 because different key objects may return the same hash code, the dictionary uses the Equals () method to compare keys. The dictionary checks whether the two keys A and B are equal, and calls the. Equals (B) method. This indicates that the following conditions must always be true:
If A. Equals (B) returns true, A. GetHashCode () and B. GetHashCode () always return the same hash code.
It sounds strange, but it is important. If the preceding conditions are not true, the dictionary can still work, but it will appear. After an object is put in the dictionary, it will no longer be retrieved, or an error item will be returned.
Therefore, if an override version is provided for the Equals () method, but the GetHashCode () method is not provided, the C # compiler displays a warning.

For System. Object, this condition is true. Because the Equals () method only compares references, the GetHashCode () method actually returns a hash code based on the Object address. This indicates that if the hash is based on a key and the key is not overwritten, the hash can work, but keys are considered equal only when the objects are identical. That is to say, when an object is put in the dictionary, it must be associated with the reference of the key. You cannot instantiate another key object with the same value in the future. If the Equals () method and GetHashCode () method are not overwritten, it is not convenient to use the type in the dictionary.

System. String implements the IEquatable interface and reloads the GetHashCode () method. The Equals () method provides a comparison of values. The GetHashCode () method returns a hash code based on the string value. Therefore, it is convenient to use strings in the dictionary as keys.

Numbers (such as Int32) also implement the IEquatable interface and overload the GetHashCode () method. However, the hash code returned by these types can only be mapped to values. If the number used as the key is not distributed within the possible Integer Range, the average distribution rule of the key value cannot be satisfied if the integer is used as the key. Therefore, the optimal performance cannot be achieved. Int32 is not suitable for dictionary use.

If the required key type does not implement the IEquatable interface and the GetHashCode () method is reloaded based on the key value stored in the dictionary, you can create a comparator that implements the IEqualityComparer <T> interface. The IEqualityComparer <T> interface defines the GetHashCode () method and Equals () method, and uses the passed object as a parameter. This provides implementation methods different from object types.

2. Demo dictionary
Create an employee ID structure and use it as the dictionary key. The data stored in the dictionary is an Employee-type object.
The member of this structure is a prefix character and a number of employees. Both variables are read-only and can only be initialized in the constructor. Keys in the dictionary should not be changed, which must be ensured.

Public struct EmployeeId: IEquatable <EmployeeId> {private readonly char prefix; private readonly int number; public EmployeeId (string id) {Contract. Requires <ArgumentNullException> (id! = Null); prefix = (id. toUpper () [0]; int numLength = id. length-1; try {number = int. parse (id. substring (1, numLength> 6? 6: numLength);} catch (FormatException) {throw new Exception ("Invalid EmployeeId format") ;}} public override string ToString () {return prefix. toString () + string. format ("{000000:}", number) ;}// because the integer value range is not filled, the GetHashCode method moves the number 16 to the left, then compare or operate with the original number, // multiply the result by the hexadecimal number 0x15051505. In this way, the hash code is evenly distributed in the integer value area. 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);} // compare the values of two EmployeeId objects: 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; public Employee (EmployeeId id, string name, decimal salary) {this. id = id; this. name = name; this. salary = salary;} public override string ToString () {return String. format ("{0 }:{ 1,-20} {2: C}", id. toString (), name, salary );}}

Client code:

Static void Main () {// The constructor specifies the capacity of 31 elements. Capacity is generally a prime number. // If a value that is not a prime number is specified, the Dictionary <TKey, TValue> class uses a prime number var employees = new Dictionary <EmployeeId, employee> (31); var idTony = new Employee ID ("C3755"); var tony = new Employee (idTony, "Tony Stewart", 379025.00 m); employees. add (idTony, tony); Console. writeLine (tony); var idCarl = new EmployeeId ("F3547"); var carl = new Employee (idCarl, "Carl Edwards", 403466.00 m); employees. add (idCarl, carl); Console. writeLine (carl); var idKevin = new EmployeeId ("C3386"); var kevin = new Employee (idKevin, "Kevin Harwick", 415261.00 m); employees. add (idKevin, kevin); Console. writeLine (kevin); var idMatt = new EmployeeId ("F3323"); var matt = new Employee (idMatt, "Matt Kenseth", 1589390.00 m); employees [idMatt] = matt; console. writeLine (matt); var idBrad = new EmployeeId ("D3234"); var brad = new Employee (idBrad, "Brad Keselowski", 322295.00 m); employees [idBrad] = brad; console. writeLine (brad );}

 

3. Lookup class
The Dictionary <TKey, TValue> class allows each key to be associated with a value. The Lookup <TKey, TElement> class maps keys to a value set. This class is implemented in the assembly System. Core and defined by System. Linq.

The Lookup <TKey, TElement> class cannot be created as a general dictionary. You must call the ToLookup () method. This method returns a Lookup <TKey, TElement> object. The ToLookup () method is an extension method that can be used to implement all classes of the IEnumerable <T> interface.
The ToLookup () method requires a Func <TSource, Tkey>, Func <TSource, Tkey> to define the selector.

  

Static void Main () {var racers = new List <Racer> (); racers. add (new Racer (26, "Jacques", "queue eneuve", "Canada", 11); racers. add (new Racer (18, "Alan", "Jones", "Australia", 12); racers. add (new Racer (11, "Jackie", "Stewart", "United Kingdom", 27); racers. add (new Racer (15, "James", "Hunt", "United Kingdom", 10); racers. add (new Racer (5, "Jack", "Brabham", "Australia", 14); // the same object in the country is associated with a key var lookupRacers = racers. toLookup (r => r. country); foreach (Racer r in lookupRacers ["Australia"]) {Console. writeLine (r );}}

Output:
Alan Jones
Jack Brabham

4. Ordered dictionary
The SortedDictionary <TKey, TValue> class is a binary search tree in which elements are sorted by keys. This key type must implement the IComparable <TKey> interface.
If the key types cannot be sorted, you can also create a comparator that implements the IComparer <TKey> interface and use the comparator as a parameter of the constructor of the ordered dictionary.
SortedDictionary <TKey, TValue> and SortedList <TKey, TValue> (http://www.cnblogs.com/afei-24/p/6830376.html:
* The SortedList <TKey, TValue> class uses less memory than the SortedDictionary <TKey, TValue> class.
* SortedDictionary <TKey, TValue> elements can be inserted and deleted quickly.
* If you do not need to change the capacity when filling the set with sorted data, ortedList <TKey, TValue> is faster.

Related Article

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.