A dictionary represents a complex data structure that allows elements to be accessed by a key. A dictionary is also known as a map or hash table.
The main feature of a dictionary is the ability to quickly find values by key. It is also free to add and remove elements, which is somewhat like list<t> (http://www.cnblogs.com/afei-24/p/6824791.html), but does not move the performance overhead of subsequent elements in memory.
is a simplified representation, the key converts bits to a hash. A hash is used to create a number that associates an index with a value. The index then contains a link to a value. An index item can have multiple values associated with it, and the index can be stored as a tree structure.
the. NET Framework provides several dictionary classes. The main class is dictionary<tkey,tvalue>.
1. Type of key
The type used as a key in a dictionary must override the GetHashCode () method of the object class. As long as the dictionary class needs to determine the location of the element, it calls the GetHashCode () method. The int returned by the GetHashCode () method has a dictionary that calculates the index at which to place the element. This algorithm is described later, now only need to know that it involves a prime number, so the capacity of the dictionary is a prime number.
the implementation code of the GetHashCode () method must meet the requirements:
* The same object should always return the same value
* Different objects can return the same value
* It should be performed faster and the calculation overhead is small
* It can't throw an exception
* It should use at least one instance field
* Hash code values should be evenly distributed across the range of numbers that int can store
* Hash code best does not change during the lifetime of the object
the performance of the dictionary depends on the implementation code of the GetHashCode () method.
The hash code value should be evenly distributed over the reason that int can store this number range:
If the hash code value returned by the two keys gets the same index, the dictionary class must look for the nearest available idle location to store the second data item, which requires a certain search to retrieve the item later. Obviously this degrades performance, and if many keys have the same index at the time of sorting, this conflict is more likely to occur. Based on how Microsoft's algorithm works, the calculated hash code values are evenly distributed across int. This risk is minimized between MinValue and Int.maxvalue.
In addition to implementing the GetHashCode () method, the key type must also implement IEQUATABLE<T>. The Equals () method, or override the Object.Equals () method. 0 The dictionary uses the Equals () method to compare keys because different key objects may return the same hash code. The dictionary checks if two keys A and B are equal and calls the A.equals (b) method. This indicates the need to ensure that the following conditions are always true:
if A.equals (B) returns True, A.gethashcode () and B.gethashcode () always return the same hash code.
It sounds a little strange, but it's important. If the above conditions are not true, the dictionary can still work, but it will appear, when an object is placed in a dictionary, it is no longer retrieved, or the wrong item is returned.
Therefore, if you provide an overridden version for the Equals () method, but do not provide an overridden version of the GetHashCode () method, the C # compiler displays a warning.
for System.Object, this condition is true because the Equals () method is only a comparison reference, and the GetHashCode () method actually returns a hash code based only on the object address. This means that if the hash list is based on a key that does not override these methods, the hash list can work, but only the objects are identical and the keys are considered equal. In other words, when you place an object in a dictionary, you must associate it with a reference to that key. You cannot instantiate another key object later with the same value. If you do not override the Equals () method and the GetHashCode () method, it is not convenient to use the type in the dictionary.
The System.String implements the IEquatable interface and overloads the GetHashCode () method. The Equals () method provides a comparison of values, and the GetHashCode () method returns a hash code based on the value of the string. Therefore, it is convenient to use the string in the dictionary in the key.
A numeric type (such as Int32) also implements the IEquatable interface and overloads the GetHashCode () method. However, the hash code returned by these types can only be mapped to values. If the number that you want to use as the key itself is not distributed within the range of possible integer values, using an integer as a key does not satisfy the average distribution rule for the key value, and therefore does not achieve optimal performance. Int32 is not suitable for use in dictionaries.
If you need to use a key type that does not implement the IEquatable interface, and you overload the GetHashCode () method based on the key values stored in the dictionary, you can create a comparer that implements the Iequalitycomparer<t> interface. The Iequalitycomparer<t> interface defines the GetHashCode () method and the Equals () method, and passes the object as a parameter, which provides a different implementation than the object type.
2. Demo Dictionary
creates an employee ID (EMPLOYEEID) structure that is used as the key for the dictionary. The data stored in the dictionary is an object of type employee.
The members of the struct are a prefix character and a number that represents the employee. Both of these variables are read-only and can only be initialized in constructors. The keys in the dictionary should not be changed, which must be guaranteed.
Public structEmployeeid:iequatable<employeeid> { Private ReadOnly Charprefix; Private ReadOnly intNumber ; PublicEmployeeId (stringID) {contract.requires<ArgumentNullException> (id! =NULL); Prefix= (ID. ToUpper ()) [0]; intNumlength = ID. Length-1; Try{ number=int. Parse (ID. Substring (1, Numlength >6?6: Numlength)); } Catch(FormatException) {Throw NewException ("Invalid EmployeeId Format"); } } Public Override stringToString () {returnPrefix. ToString () +string. Format ("{0,6:000000}", number); } //since the integer value range is not filled, the GetHashCode method moves the number 16 bits to the left, and then the original number is different or manipulated.//The result is multiplied by the 16 decimal 0x15051505. In this way, the hash code is evenly distributed across the integer value area. Public Override intGetHashCode () {return(number ^ number << -) *0x15051505; } Public BOOLEquals (EmployeeId other) {if(Other = =NULL)return false; return(prefix = = Other.prefix && Number = =other.number); } //Compare the values of two EmployeeID objects Public Override BOOLEquals (Objectobj) { returnEquals ((EmployeeId) obj); } Public Static BOOL operator==(EmployeeId left, EmployeeId right) {returnLeft . Equals (right); } Public Static BOOL operator!=(EmployeeId left, EmployeeId right) {return! (left = =Right ); } } Public classEmployee {Private stringname; Private decimalsalary; Private ReadOnlyEmployeeId ID; PublicEmployee (EmployeeId ID,stringNamedecimalsalary) { This. ID =ID; This. Name =name; This. Salary =salary; } Public Override stringToString () {returnString.Format ("{0}: {1, -20} {2:C}", ID. ToString (), name, salary); } }
Client code:
Static voidMain () {//The constructor specifies the capacity of 31 elements. Capacity is generally prime. //If you specify a value that is not a prime number, the,dictionary<tkey,tvalue> class uses a prime that is immediately following the specified integer varEmployees =NewDictionary<employeeid, Employee> ( to); varIdtony =NewEmployeeId ("C3755"); varTony =NewEmployee (Idtony,"Tony Stewart",379025.00m); Employees. ADD (Idtony, Tony); Console.WriteLine (Tony); varIdcarl =NewEmployeeId ("F3547"); varCarl =NewEmployee (Idcarl,"Carl Edwards",403466.00m); Employees. ADD (Idcarl, Carl); Console.WriteLine (Carl); varIdkevin =NewEmployeeId ("C3386"); varKevin =NewEmployee (Idkevin,"Kevin Harwick",415261.00m); Employees. ADD (Idkevin, Kevin); Console.WriteLine (Kevin); varIdmatt =NewEmployeeId ("F3323"); varMatt =NewEmployee (Idmatt,"Matt Kenseth",1589390.00m); Employees[idmatt]=Matt; Console.WriteLine (Matt); varIdbrad =NewEmployeeId ("D3234"); varBrad =NewEmployee (Idbrad,"Brad Keselowski",322295.00m); Employees[idbrad]=Brad; Console.WriteLine (Brad); }
3.Lookup class
The Dictionary<tkey,tvalue> class supports a value associated with each key. The Lookup<tkey,telement> class maps a key to a set of values. This class is implemented in assembly System.core and is defined with System.Linq.
The Lookup<tkey,telement> class cannot be created as a generic dictionary, and must call the ToLookup () method, which 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 voidMain () {varRacers =NewList<racer>(); Racers. ADD (NewRacer ( -,"Jacques","Villeneuve","Canada", One)); Racers. ADD (NewRacer ( -,"Alan","Jones","Australia", A)); Racers. ADD (NewRacer ( One,"Jackie","Stewart","Kingdom", -)); Racers. ADD (NewRacer ( the,"James","Hunt","Kingdom",Ten)); Racers. ADD (NewRacer (5,"Jack","Brabham","Australia", -)); //country the same object is associated to a key varLookupracers = Racers. ToLookup (R =r.country); foreach(Racer Rinchlookupracers["Australia"
Output:
Alan Jones
Jack Brabham
4. Ordered dictionaries
The Sorteddictionary<tkey,tvalue> class is a binary search tree in which the elements are sorted by key. The key type must implement the Icomparable<tkey> interface.
If the type of the key cannot be sorted, you can also create a comparer that implements the Icomparer<tkey> interface, using the comparer as a parameter to the constructor of an ordered dictionary.
The difference between sorteddictionary<tkey,tvalue> and ordered list sortedlist<tkey,tvalue> (http://www.cnblogs.com/afei-24/p/6830376.html):
The *sortedlist<tkey,tvalue> class uses less memory than sorteddictionary<tkey,tvalue>.
The insert and delete operations of the *sorteddictionary<tkey,tvalue> element are relatively fast.
* When populating a collection with sorted data, it is faster to change the capacity,ortedlist<tkey,tvalue>.
Dictionary of C # collections