Summary:
This paper mainly records my hashcode and equals two knowledge points of the learning Process.
From the time of students to learn java, know hashcode and equals the two methods, the use of the Equals method is particularly frequent, to say the equals method, then must not hashcode this Method. The following to tidy up my current understanding of these two methods, if there are errors in the text, please correct me, thank you.
Hash code, or hash code value, is an integer value produced by an object. There is no regularity in its generation. The hash code can get the information in the object and turn it into the "relative unique" integer value of that Object. All objects have a hash code.
Directly post the JDK source code, clear.
Object:
native int hashcode ();p ublic boolean equals (Object obj) { return (this= = obj);}
We notice that the hashcode of object has a native modifier in front of it, what does this modifier mean?
Native is local, and native-modified methods are called local METHODS. In the Java source program with the keyword "native" declaration, does not provide a function body, its implementation is written in a separate file using the C + + language, The rules are written in accordance with the Java local interface Specification (jni). In the case of jane, the callable method that is declared in Java is implemented by using C + +. In other words, the implementation of the Object's Hashcode method is implemented externally by a non-java language, such as C (to further understand native, please search by itself), where the Hashcode method returns the address of the memory Object.
The Equals method of an Object object compares the memory addresses of the objects for Equality.
Then take a look at these two methods of the string class:
/** The value is used for character Storage. */private Final char value[];/** Cache the hash code for the string */private int hash; Default to 0public int hashcode () { int h = hash; If (h = = 0 && value.length > 0) { char val[] = value; for (int i = 0; i < value.length; i++) { h = + * H + val[i]; } hash = h; } Return h;}
H = * H + val[i]; Why does the calculation here use 31? Look at the exact words in chapter 42nd of the second edition of effective Java:
"31 is chosen because it is an odd number, and if the multiplier is an even number and the multiplication overflows, the information is lost because multiplying with 2 is equivalent to the shift operation." The benefits of using prime numbers are not obvious, but it is customary to use prime numbers to calculate hash results.
31 There is a good feature, that is, using shift and subtraction instead of multiplication, you can get better performance: 31*i== (i<<5)-i. Today's VMs can automatically do this Optimization. ”
Look at the Equals method of String:
public boolean equals (Object Anobject) { if (this = = Anobject) { return true; } If (anobject instanceof String) { string anotherstring = (string) anobject; int n = value.length; if (n = = AnotherString.value.length) { char v1[] = value; Char v2[] = anotherstring.value; int i = 0; While (n--! = 0) { If (v1[i]! = v2[i]) return false; i++; } return true; } } Return false;}
if (this = = Anobject) How does this explain? Not to understand ...
If the passed-in parameter anobject is of type string, then the loop iterates over each of the character arrays in which the two strings correspond, and returns False if one character is not equal.
Then look at byte:
public int hashcode () { return (int) value;} public boolean equals (Object obj) {if (obj instanceof Byte) {return value = = ((Byte) obj). bytevalue (); Return false;}
Character:
public int hashcode () { return (int) value, } public boolean equals (Object obj) { if (obj instanceof Character) { return value = = ((Character) obj). charvalue (); } return false; }
Short:
public int hashcode () { return (int) value, } public boolean equals (Object obj) { if (obj instanceof short) { C11/>return value = = ((short) obj). shortvalue (); } return false; }
Integer:
public int hashcode () { return value; } public boolean equals (Object obj) { if (obj instanceof Integer) { return value = = ((Integer) obj). intvalue (); } return false; }
The above four types of these two methods code is relatively simple, at a glance.
See Float:
public int hashcode () { return floattointbits (value); } public boolean equals (Object obj) { return (obj instanceof Float) && (floattointbits Floattointbits(value)); }
Floattointbits ()? What the hell is this method? Paste out the source code:
floattointbits (float Value) { int result = Floattorawintbits (value); Check for NaN based on the values of bit fields, maximum //exponent and nonzero significand. If ((result & floatconsts.exp_bit_mask) = = floatconsts.exp_bit_mask) && (result & floatconsts.signif_bit_mask)! = 0) result = 0x7fc00000; return result; }
Do not know what meaning, online search for an explanation, also posted here:
"in accordance with the IEEE 754 standard, 32-bit floating-point numbers in the computer binary storage form a total of three parts: S (1-bit, symbol) E (8-bit, order) M (23-bit, Mantissa)
As an example, float.floattointbits (20.5f) is calculated as Follows:
20.59D=10100.1B=1.01001*2^4B Index E=4
S=0--> positive e=4+127=131d=10000011b--> True index e becomes order e and 127 m=01001b
The 32-bit 2-binary storage is: 0 10000011 01001000000000000000000
Convert to 10 binary as 1101266944 "
See here, meaning is to convert floating-point numbers to int value, compare with each other, here is also the Value.
Then look at the double type:
public int hashcode () { doubletolongbits(value); return (int) (bits ^ (bits >>> a)); } public boolean equals (Object obj) { return (obj instanceof Double) && (doubletolongbits(( Double) Obj) (value) = = doubletolongbits(value)); }
Doubletolongbits (), still do not understand, put out the source Code.
public static long Doubletolongbits (double Value) { Long result = Doubletorawlongbits (value); Check for NaN based on the values of bit fields, maximum //exponent and nonzero significand. If ((result & doubleconsts.exp_bit_mask) = = doubleconsts.exp_bit_mask) && (result & doubleconsts.signif_bit_mask)! = 0L) result = 0x7ff8000000000000l; return result; }
On-line explanation of Doubletolongbits (), posted out to help understand:
Doubletolongbits Method: Returns the representation of a specified floating-point value, based on the IEEE 754 floating-point double format ("double Format") bit Layout. The 63rd bit (the mask 0x8000000000000000l The selected Bit) represents the sign of the floating-point number, the 62nd to 52nd bit (the mask 0x7ff0000000000000l The selected Bit) represents the exponent, and the 51st to No. 0 bit (mask 0X000FFFFFFFFFFFFFL The selected Bit) represents a valid number of floating-point numbers (sometimes called mantissa). If the argument is positive infinity, The result is 0x7ff0000000000000l; if the argument is negative infinity, The result is 0xfff0000000000000l; if the argument is NaN, the result is 0x7ff8000000000000l. In all cases, The result is a long integer that is assigned to the Longbitstodouble (long) method to produce a floating-point value that is the same as the doubletolongbits parameter (except when all Nan values are compressed into a "canonical" nan value).
It is also known that the double type compares the Value.
Look at the two methods of the Boolean type:
public int hashcode () { return value? 1231:1237; } public boolean equals (Object obj) { if (obj instanceof boolean) { return value = = ((boolean) obj). booleanvalue (); c6/>} return false; }
What does the Boolean-type Hashcode method mean? Ask the great God to explain ...
Look at these two methods of arrays:
Hashcode () Source Code:
Type long array public static int hashcode (long A[]) {if (a = = Null) return 0; int result = 1; For (long element:a) {int elementhash = (int) (element ^ (element >>> 32)); result = * result + elementhash; } return result; }//int array public static int hashcode (int A[]) {if (a = = Null) return 0; int result = 1; For (int element:a) result = = * result + element; Return result; }//short array public static int hashcode (short A[]) {if (a = = Null) return 0; int result = 1; For (short element:a) result = * result + element; Return result; }//char array public static int hashcode (char A[]) {if (a = = Null) return 0; int result = 1; For (char element:a) result = * result + element; Return result; }//byte array public static int hashcode (byte A[]) {if (a = = Null) return 0; int result = 1; For (byte element:a) result = * result + element; Return result; }//boolean array public static int hashcode (boolean A[]) {if (a = = Null) return 0; int result = 1; For (boolean element:a) result = * result + (element 1231:1237); Return result; }//float array public static int hashcode (float A[]) {if (a = = Null) return 0; int result = 1; For (float element:a) result = * result + float.floattointbits (element); Return result; }//double array public static int hashcode (double A[]) {if (a = = Null) return 0; int result = 1; For (double element:a) {long bits = double.doubletolongbits (element); result = * result + (int) (bits ^ (bits >>> 32)); } return result; }//Object array public static inT hashcode (Object a[]) {if (a = = Null) return 0; int result = 1; For (Object element:a) result = * result + (element = = null? 0:element.hashcode ()); Return result; }
An array is an iterative calculation of the hash value of each element in the array, obtaining a hash Value.
equals () method Source Code:
public static Boolean equals (long[] a, long[] a2) {if (a==a2) return true; If (a==null | | A2==null) return false; int length = a.length; If (a2.length! = Length) return false; For (int i=0; i<length; i++) If (a[i]! = a2[i]) return false; Return true; } public static Boolean equals (int[] a, int[] a2) {if (a==a2) return true; If (a==null | | A2==null) return false; int length = a.length; If (a2.length! = Length) return false; For (int i=0; i<length; i++) If (a[i]! = a2[i]) return false; Return true; } public static Boolean equals (short[] a, short A2[]) {if (a==a2) return true; If (a==null | | A2==null) return false; int length = a.length; If (a2.length! = Length) return false; For (int i=0; i<length; I++) if (a[i]! = a2[i]) return false; Return true; } public static Boolean equals (char[] a, char[] a2) {if (a==a2) return true; If (a==null | | A2==null) return false; int length = a.length; If (a2.length! = Length) return false; For (int i=0; i<length; i++) If (a[i]! = a2[i]) return false; Return true; } public static Boolean equals (byte[] a, byte[] a2) {if (a==a2) return true; If (a==null | | A2==null) return false; int length = a.length; If (a2.length! = Length) return false; For (int i=0; i<length; i++) If (a[i]! = a2[i]) return false; Return true; } public static Boolean equals (boolean[] a, boolean[] a2) {if (a==a2) return true; If (a==null | | A2==null) return false; int length = a.length; If (a2.length! = Length) return false; For (int i=0; i<length; i++) If (a[i]! = a2[i]) return false; Return true; } public static Boolean equals (double[] a, double[] a2) {if (a==a2) return true; If (a==null | | A2==null) return false; int length = a.length; If (a2.length! = Length) return false; For (int i=0; i<length; i++) if (double.doubletolongbits (a[i])!=double.doubletolongbits (a2[i])) Return false; Return true; } public static Boolean equals (float[] a, float[] a2) {if (a==a2) return true; If (a==null | | A2==null) return false; int length = a.length; If (a2.length! = Length) return false; For (int i=0; i<length; i++) if (float.floattointbits (a[i])!=float.floattointbits (a2[i]) retUrn false; Return true; } public static Boolean equals (object[] a, object[] a2) {if (a==a2) return true; If (a==null | | A2==null) return false; int length = a.length; If (a2.length! = Length) return false; For (int i=0; i<length; i++) {Object O1 = a[i]; Object O2 = a2[i]; If (! ( o1==null? O2==null:o1.equals (o2))) return false; } return true; }
The Equals () method of an array is whether the original array object is equal to each element in the parameter array object, and of course there are some judgments ahead.
now, The main goal is to figure out how Java compares two objects for Equality. On the inside is the realization of the idea, but also need to be slowly elaborated.
According to "effective java" this Book's content, carries on the summary:
When we want to override the equals method, we must abide by his universal convention, otherwise an exception will Occur.
- Symmetry (symmetric): any non-null =null reference value x y, if X.equals (y) returns is "true", then Y.equals (x) should also return "true".
- Reflexive (reflexive): any non-null =null reference value X,x.equals (x) must return is "true".
- transitivity (transitive): any non-null =null reference value x y z, if x.equals (y) returns is "true", and Y.equals (z) return is "true", then z.equals (x) should also return "true".
- Consistency (consistent): any non-null =null reference value x y, if X.equals (y) returns is "true", as long as the X and Y contents remain constant, no matter how many times you repeat X.equals (y), the return is "true".
- In any case, x.equals (null), return Forever is "false"; x.equals (and x objects of different types) always return false
When we rewrite the equals method, we also rewrite the hashcode method, because we want to ensure that if two objects equals equals true, then the hashcode return value must also be equal
1. When the Equals method of two objects returns true, the Hashcode return value must be equal, and if the two object Equals method return value is false, the return value of the hashcode of the two objects may be equal.
2, when the hashcode return value of two objects is equal, the Equals method of two objects is not necessarily true (hash conflict), but if the hashcode return value of two objects is not equal, the return value of the equals of this object must be False.
Resources:
1, "effective Java" Second Edition
2, Analysis of Hashcode method (this Blog I feel very good writing, here thank the Author. )
The above content also needs to be added slowly, if the article has the mistake, please pointing, thanks.
Java basics: hashcode and equals personal learning record