Hash and hash code

Source: Internet
Author: User

According to your imagination, we can find out the groudhog GH = ghog. newinstance (3); this key, but not found

Package CN. partner4java. hashcode;/*** each groudhog is assigned an identification number * @ author partner4java **/public class groudhog {protected int number; Public groudhog (INT number) {This. number = Number ;}@ overridepublic string tostring () {return "groudhog #" + number ;}} package CN. partner4java. hashcode; import Java. util. random;/*** predition class contains a Boolean value and a tostring method. * Boolean uses Java. util. randrom () to initialize * @ author partner4java **/public class Prediction {Private Static random = new random (47); Private Boolean shadow = random. nextdouble ()> 0.5; @ overridepublic string tostring () {If (Shadow) {return "six more weeks of winter! ";}Else {return" Early Spring ";}} package CN. partner4java. hashcode; import Java. lang. reflect. constructor; import Java. util. hashmap; import Java. util. map;/*** the detectspring method uses the reflection mechanism to instantiate and use the groundhog class or any class derived from the groundhog. * @ Author partner4java **/public class springdetector {public static <t extends groudhog> void detectspring (class <t> type) throws exception {constructor <t> ghog = type. getconstructor (Int. class); Map <groudhog, prediction> map = new hashmap <groudhog, prediction> (); For (INT I = 0; I <10; I ++) {map. put (ghog. newinstance (I), new prediction ();} system. out. println ("map =" + map); groudhog GH = ghog. newinstance (3); system. out. println ("looking up prediction for" + GH); If (map. containskey (GH) {system. out. println (map. get (GH);} else {system. out. println ("key not found:" + GH) ;}} public static void main (string [] ARGs) throws exception {detectspring (groudhog. class );}}

The problem is that groundhog automatically inherits from the base class object. Therefore, the hashcode method of the object is used to generate the hash code. By default, the hash code is calculated using the object address.
Therefore, the hash codes of the two groundhog (3) are different.

However, you must overwrite the hashcode and the equals () method, which is also part of the object.
Hashmap uses equals () to determine whether the current key is the same as the existing key in the table.

The correct equals method must meet the following five conditions:
1. reflexive: True must be returned for any non-null reference values X, X. Equals (X.
If it violates this rule, when you add the instance of this class to the collection, the contains of this collection will tell you that it does not contain the instance you just added.

2. Symmetry: For any non-null reference values X and Y, if and only if y. when equals (x) returns true, X. equals (y) must return true.
An instance comparison is case-insensitive. However, in turn, the comparison is case-insensitive, leading to asymmetry.

3. transitive: For any non-null reference values X, Y, and Z, if X. equals (y) returns true, and Y. equals (z) also returns true, then X. equals (z) must also return true.
The information added to the subclass will affect the comparison result of equals.

4. consistent: For any non-null reference values X and Y, as long as the information used in the comparison operation of equals in the object is not modified, X is called multiple times. equals (y) returns true in the same way, or false in the same way.
Do not rely on unreliable resources for the equals method.

5. non-null (non-Nullity): For any non-null reference value X, X. Equals (null), false must be returned.

The default equals method is to compare the memory address.
Add the hashcode and equals methods to groundhog:

Package CN. partner4java. hashcode;/*** each groudhog is assigned an identification number * @ author partner4java **/public class groudhog {protected int number; Public groudhog (INT number) {This. number = Number ;}@ overridepublic string tostring () {return "groudhog #" + number ;}@ overridepublic int hashcode () {final int prime = 31; int result = 1; result = prime * result + number; return result;} @ overridepublic Boolean equals (Object o BJ) {If (this = OBJ) return true; If (OBJ = NULL) return false; If (getclass ()! = Obj. getclass () return false; groudhog Other = (groudhog) OBJ; If (number! = Other. Number) return false; return true ;}}

Now we can find it.




Understanding hashcode ()
Hash is used to search for another object. However, using treemap or using map can also achieve this goal.


Package CN. partner4java. hashcode; import java. util. Map. Entry;/*** map. entryset () method must generate a map. Entry <K, V> object set. However, map. Entry is an interface used to describe the implementation-dependent structure. Therefore, if you want to create your own map type. * @ Author partner4java ** @ Param <k> * @ Param <v> */public class mapentry <K, V> implements entry <K, V> {private K key; private V value; Public mapentry (K key, V value) {super (); this. key = key; this. value = value;} public K getkey () {return key;} // public void setkey (K key) {// This. key = key; //} public v getvalue () {return value;} public v setvalue (V v) {v result = value; value = V; return result ;}@ overrid Epublic int hashcode () {final int prime = 31; int result = 1; Result = prime * result + (Key = NULL )? 0: Key. hashcode (); Result = prime * result + (value = NULL )? 0: value. hashcode (); return result ;}@ overridepublic Boolean equals (Object OBJ) {If (this = OBJ) return true; If (OBJ = NULL) return false; if (getclass ()! = Obj. getclass () return false; mapentry Other = (mapentry) OBJ; If (Key = NULL) {If (other. Key! = NULL) return false;} else if (! Key. Equals (other. Key) return false; If (value = NULL) {If (other. value! = NULL) return false;} else if (! Value. equals (Other. value) return false; return true ;}@ overridepublic string tostring () {return "mapentry [Key =" + key + ", value = "+ value +"] ";}} package CN. partner4java. hashcode; import Java. util. abstractmap; import Java. util. arraylist; import Java. util. hashset; import Java. util. iterator; import Java. util. list; import Java. util. map; import Java. util. set; import net. mindview. util. countries;/*** opposite to the hash, use a pair of Rraylist implements a map. * The put () method only puts the key and value in the corresponding arraylist. To be consistent with the map interface, he must return the old key or return NULL without any old key. * If a key exists, it is used to search for a numeric index indicating its position in the Keys list, and this number is used as an index to generate a value associated with the values list. * @ Author partner4java ** @ Param <k> * @ Param <v> */public class slowmap <K, V> extends abstractmap <K, v> {private list <k> keys = new arraylist <k> (); Private list <v> values = new arraylist <v> (); Public v get (Object key) {If (! Keys. contains (key) {return NULL;} return values. get (keys. indexof (key);} public v put (K key, V value) {v oldvalue = get (key); // The old value or nullif (! Keys. contains (key) {keys. add (key); values. add (value);} else {values. set (keys. indexof (key), value);} return oldvalue;} @ overridepublic set <map. entry <K, V> entryset () {set <map. entry <K, V> set = new hashset <map. entry <K, V> (); iterator <k> ki = keys. iterator (); iterator <v> Vi = values. iterator (); While (Ki. hasnext () {set. add (New mapentry <K, V> (Ki. next (), Vi. next ();} return set;} public static void main (string [] ARGs) {slowmap <string, string> M = new slowmap <string, string> (); m. putall (countries. capitals (15); system. out. println (m); system. out. println (M. get ("Benin"); system. out. println (M. entryset ());}}


Hash for speed:
(The premise is to use arrays, because it is faster than thread search)
The value of hash lies in speed: hash is a fast query. Because the bottleneck lies in the query speed of the key, one solution is to maintain the sort status of the key, and then use collections. binarysearch () for query.

Hash goes further. He says Jian stays in a certain place so that he can quickly search for it. The array maintains a number generated by the key and uses it as the subscript of the array. This array is the hash code.

To solve the problem of Fixed Array capacity, different keys can generate the same subscript.

Therefore, the process of querying a value is first to calculate the hash code and then use the hash code to query the array. In general, if the hash code is the same as the conflict, it is processed by external links: the array does not directly keep the value, but maintains the list of values. Then, use the equals method to query the list value linearly. This part of the query will be slow, but if the hash function is good, the value of each position in the array will be very small. Therefore, instead of querying the entire list, the system immediately jumps to a position in the array. This is why hashmap is faster.


package cn.partner4java.hashcode;import java.util.AbstractMap;import java.util.HashSet;import java.util.LinkedList;import java.util.ListIterator;import java.util.Map;import java.util.Set;import net.mindview.util.Countries;public class SimpleHashMap<K, V> extends AbstractMap<K, V> {// Choose a prime number for the hash table// size,to achieve a uniform distributionstatic final int SIZE = 997;// You can't have a physical array of generics,// but you can upcast to one;@SuppressWarnings("unchecked")LinkedList<MapEntry<K, V>>[] buckets = new LinkedList[SIZE];@Overridepublic V get(Object key) {int index = Math.abs(key.hashCode()) % SIZE;if (buckets[index] == null)return null;for (MapEntry<K, V> iPair : buckets[index]) {if (iPair.getKey().equals(key)) {return iPair.getValue();}}return null;}@Overridepublic V put(K key, V value) {V oldValue = null;int index = Math.abs(key.hashCode()) % SIZE;if (buckets[index] == null)buckets[index] = new LinkedList<MapEntry<K, V>>();LinkedList<MapEntry<K, V>> bucket = buckets[index];MapEntry<K, V> pair = new MapEntry<K, V>(key, value);boolean found = false;ListIterator<MapEntry<K, V>> it = bucket.listIterator();while (it.hasNext()) {MapEntry<K, V> iPair = it.next();if (iPair.getKey().equals(key)) {oldValue = iPair.getValue();it.set(pair); // Replace old with newfound = true;break;}}if (!found)buckets[index].add(pair);return oldValue;}@Overridepublic Set<Map.Entry<K, V>> entrySet() {Set<Map.Entry<K, V>> set = new HashSet<Map.Entry<K, V>>();for (LinkedList<MapEntry<K, V>> bucket : buckets) {if (bucket == null)continue;for (MapEntry<K, V> mpair : bucket)set.add(mpair);}return set;}public static void main(String[] args) {SimpleHashMap<String, String> m = new SimpleHashMap<String, String>();m.putAll(Countries.capitals(25));System.out.println(m);System.out.println(m.get("ERITREA"));System.out.println(m.entrySet());}}


Overwrite hashcode ()

Each class that overwrites the equals method must also overwrite the hashcode method.
If this is not the case, it will violate the general conventions of object. hashcode, so that the class cannot work properly together with all hash-based sets. Such sets include hashmap, hashset, and hashtable.

During the execution of the referenced program, as long as the information used for the comparison operation of the equals method of the object is not modified, the same object is called multiple times, all hashcode methods must always return the same integer. During multiple executions of an application, the integers returned by each execution can be inconsistent.
If the root equals method of an object is equal, the hashcode method of any of the two objects must produce the same integer result.
If the two objects are not equal according to the equals method, calling the hashcode method of any of the two objects does not necessarily produce different integer results. However, programmers should know that generating distinct integer results for unequal objects may improve the performance of hash tables. (For example, if an entity is equal only according to the ID, but there is no id value before instantiation, the default equals returns false, but the value returned by hashcode is equal .)

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.