The analysis of a storage class is nothing more than two points: the data structure used for storage and the operating mechanism of storage.
Data structure:
Array
[Java]
/**
* The table, resized as necessary. Length MUST Always be a power of two.
*/
Transient Entry [] table;
/**
* The table, resized as necessary. Length MUST Always be a power of two.
*/
Transient Entry [] table;
Entry
Linked List format.
That is, HashMap uses the "Link Method" to handle collision issues.
Operating Mechanism:
Put, get
Put Method
[Java]
Public V put (K key, V value ){
If (key = null)
Return putForNullKey (value );
Int hash = hash (key. hashCode ());
Int I = indexFor (hash, table. length );
For (Entry <K, V> e = table [I]; e! = Null; e = e. next ){
Object k;
If (e. hash = hash & (k = e. key) = key | key. equals (k ))){
V oldValue = e. value;
E. value = value;
E. recordAccess (this );
Return oldValue;
}
}
ModCount ++;
AddEntry (hash, key, value, I );
Return null;
}
Public V put (K key, V value ){
If (key = null)
Return putForNullKey (value );
Int hash = hash (key. hashCode ());
Int I = indexFor (hash, table. length );
For (Entry <K, V> e = table [I]; e! = Null; e = e. next ){
Object k;
If (e. hash = hash & (k = e. key) = key | key. equals (k ))){
V oldValue = e. value;
E. value = value;
E. recordAccess (this );
Return oldValue;
}
}
ModCount ++;
AddEntry (hash, key, value, I );
Return null;
}
Get Method
[Java]
? Public V get (Object key ){
If (key = null)
Return getForNullKey ();
Int hash = hash (key. hashCode ());
For (Entry <K, V> e = table [indexFor (hash, table. length)];
E! = Null;
E = e. next ){
Object k;
If (e. hash = hash & (k = e. key) = key | key. equals (k )))
Return e. value;
}
Return null;
}
Public V get (Object key ){
If (key = null)
Return getForNullKey ();
Int hash = hash (key. hashCode ());
For (Entry <K, V> e = table [indexFor (hash, table. length)];
E! = Null;
E = e. next ){
Object k;
If (e. hash = hash & (k = e. key) = key | key. equals (k )))
Return e. value;
}
Return null;
}
It can be seen that the important code is:
[Java]
If (e. hash = hash & (k = e. key) = key | key. equals (k )))
If (e. hash = hash & (k = e. key) = key | key. equals (k )))
The purpose of this Code is to determine whether the two Key objects are "identical". The same here means that the two keys can be used as the same Key and completely different from each other.
In the put method, if the hashCode of the two keys is the same and the equals matches, the original value is replaced with the new value.
Test code:
[Java]
Package test. junit;
Import java. util. HashMap;
Import junit. framework. TestCase;
/**
* In HashMap, determine whether two keys are the same: first judge the hashCode and determine whether equals
* E. hash = hash & (k = e. key) = key | key. equals (k ))
* @ Author xuefeng
*
*/
Public class HashMapTest extends TestCase {
/**
* The hashCode of v1 and v4 is the same, but the equals does not match. Therefore, v1 and v4 form a linked list.
*/
Public void testKey1 (){
HashMap <Key, Value> map = new HashMap <Key, Value> ();
Key k1 = new Key (1 );
Key k4 = new Key (4 );
Value v1 = new Value (1 );
Value v4 = new Value (4 );
Map. put (k1, v1 );
Map. put (k4, v4 );
AssertEquals (v1, map. get (k1 ));
AssertEquals (v4, map. get (k4 ));
}
/**
* V1 and v4 have the same hashCode and equals, so v1 is replaced by v4, and k1 and k4 point to the same v4.
*/
Public void testKey2 (){
HashMap <Key2, Value> map = new HashMap <Key2, Value> ();
Key2 k1 = new Key2 (1 );
Key2 k4 = new Key2 (4 );
Value v1 = new Value (1 );
Value v4 = new Value (4 );
Map. put (k1, v1 );
Map. put (k4, v4); // v1 is replaced here
// AssertEquals (v1, map. get (k1 ));
AssertEquals (v4, map. get (k1 ));
AssertEquals (v4, map. get (k4 ));
}
}
Class Key {
Public int m;
Public Key (int m ){
This. m = m;
}
@ Override
Public int hashCode (){
Return m % 3;
}
}
Class Value {
Public int m;
Public Value (int m ){
This. m = m;
}
}
Class Key2 {
Public int m;
Public Key2 (int m ){
This. m = m;
}
@ Override
Public int hashCode (){
Return m % 3;
}
@ Override
Public boolean equals (Object obj ){
If (obj = null |! (Obj instanceof Key2) return false;
Key2 other = (Key2) obj;
Return this. hashCode () = other. hashCode ();
}
}
Package test. junit;
Import java. util. HashMap;
Import junit. framework. TestCase;
/**
* In HashMap, determine whether two keys are the same: first judge the hashCode and determine whether equals
* E. hash = hash & (k = e. key) = key | key. equals (k ))
* @ Author xuefeng
*
*/
Public class HashMapTest extends TestCase {
/**
* The hashCode of v1 and v4 is the same, but the equals does not match. Therefore, v1 and v4 form a linked list.
*/
Public void testKey1 (){
HashMap <Key, Value> map = new HashMap <Key, Value> ();
Key k1 = new Key (1 );
Key k4 = new Key (4 );
Value v1 = new Value (1 );
Value v4 = new Value (4 );
Map. put (k1, v1 );
Map. put (k4, v4 );
AssertEquals (v1, map. get (k1 ));
AssertEquals (v4, map. get (k4 ));
}
/**
* V1 and v4 have the same hashCode and equals, so v1 is replaced by v4, and k1 and k4 point to the same v4.
*/
Public void testKey2 (){
HashMap <Key2, Value> map = new HashMap <Key2, Value> ();
Key2 k1 = new Key2 (1 );
Key2 k4 = new Key2 (4 );
Value v1 = new Value (1 );
Value v4 = new Value (4 );
Map. put (k1, v1 );
Map. put (k4, v4); // v1 is replaced here
// AssertEquals (v1, map. get (k1 ));
AssertEquals (v4, map. get (k1 ));
AssertEquals (v4, map. get (k4 ));
}
}
Class Key {
Public int m;
Public Key (int m ){
This. m = m;
}
@ Override
Public int hashCode (){
Return m % 3;
}
}
Class Value {
Public int m;
Public Value (int m ){
This. m = m;
}
}
Class Key2 {
Public int m;
Public Key2 (int m ){
This. m = m;
}
@ Override
Public int hashCode (){
Return m % 3;
}
@ Override
Public boolean equals (Object obj ){
If (obj = null |! (Obj instanceof Key2) return false;
Key2 other = (Key2) obj;
Return this. hashCode () = other. hashCode ();
}
}