Looking at "Thinking in Java" to learn about the hash code related knowledge, in this summary.
Let's take a look at an example
class student{protected int id;//The members of the current class and the classes that inherit the class can be accessed.
public Student (int id) {this.id = ID;
@Override public String toString () {return "Student #" + ID;
Class score{private static Random Random = new Random (47);
private int score = Random.nextint (100);
@Override public String toString () {return string.valueof (score); } public class Hashcodetest {public static <t extends student> void Studscore (class<t> type) throws E
xception{constructor<t> stud = Type.getconstructor (Int.class);
The reflection mechanism is used to instantiate and use the Student class and any class map<student derived from Student, score> Map = new hashmap<> ();
for (int i = 0; i < i++) {map.put (Stud.newinstance (i), New Score ());
} System.out.println ("map" + map);
Student Student = stud.newinstance (3);//using the Student with ID 3 as key System.out.println ("Find student:" + Student); if (map.cOntainskey (Student)) {System.out.println (Map.get (student));
}else {System.out.println ("This student does not exist");
} public static void Main (string[] args) throws exception{Studscore (Student.class);
}
}
Output
Map{student #1 =55, Student #4 =61, Student #5 =29, Student #3 =61, Student #8 =22, Student #7 =0, Student #0 =58, Student #2 = 93, Student #9 =7, Student #6 =68}
looking for students: Student #3
This student does not exist
But as a result, it cannot find the key with ID 3. The problem is that student is automatically inherited from the base class object, where the hash code is generated using the object's Hashcode () method, which is calculated by default by using the address of the objects. The instance of the first Student (3) and the second hash code are different. So I can't find it.
Therefore, it is necessary to cover the hashcode () method appropriately. and overwrites the Equals method at the same time. Because HashMap uses equals () to determine whether the current key is the same as the key that exists in the table
Equals () satisfies the following conditions:
1 reflexivity for any x, x.equals (x) must return True.
2) The symmetry is the same for any x,y,x.equals (y) and y.equals (x) return value.
3 transitivity for any x,y,z, the x.equals (z) return value is the same if X.equals (y) is the same as the Y.equals (z) return value.
4 consistency for any x,y, no matter how many times x.equals (y) executes, the return value is either True or false.
5) for any x!= null, x.equals (NULL) returns FALSE.
So to use your own class as a HashMap key, you must overwrite both hashcode () and Equals ().
Class Student2 extends student{public
Student2 (int id) {
super (ID);
}
@Override public
int hashcode () {
return id;//returns ID as hash code
} @Override
public
boolean equals (Object obj) {return
obj instanceof Student2 && (id = = ((Student2) obj). id);
Instanceof checks to see if this object is null and then compares it based on the actual ID in each object
}
} public
class HashCode2 {public
static void Main (string[] args) throws Exception {
hashcodetest.studscore (student2.class);
}
}
Output
Map{student #0 =58, Student #1 =55, Student #2 =93, Student #3 =61, Student #4 =61, Student #5 =29, Student #6 =68, Student #7 = 0, Student #8 =22, Student #9 =7}
looking for students: Student #3
61
Hash for Speed
Linear query is the slowest query method
The hash stores the key somewhere so that it can be found quickly. The fastest data structure for storing a set of elements is an array, so it is used to represent the information of the key.
Instead of saving the key itself, the array generates a number from the key object, which is the subscript of the array, which is the hash code.
Conflicts have external link processing, the array does not directly save the value, but save the list. Then use the Equals () method for a linear query on the values in the list. (This part of the query will be slower)
The "slot" (slot) of the hash table is often called the bucket bit (bucket), the Java hash function uses the integer number of 2 for the second party (remainder and division is the slowest operation, using the hash code of the integer square length of 2, you can use a mask instead of division to reduce the cost of% operations in Get ()).
Overlay hashcode ()
Whenever you call Hashcode () on the same object, you should generate the same value. and cannot rely on variable data.
You should also not make hashcode () dependent on the object information of uniqueness.
Take the string class as an example, if there are multiple string objects in the program that contain the same string sequence, then the string objects are mapped to the same memory area.
public class Stringtest {public
static void Main (string[] args) {
string str1 = new String ("Hello");
String str2 = new String ("Hello");
System.out.println (Str1.hashcode ());
System.out.println (Str2.hashcode ());
System.out.println (Str1.equals (str2));
System.out.println (str1 = = str2);
The double equals is the contents of the comparison stack, the original data type and address are placed in the stack. The equals are compared to the contents of the heap based on the address.
}
}
Output
99162322
99162322
true
false
For string, Hashcode () is obviously based on the contents of a string. Hash codes are not necessarily unique depending on the content of the object, but the Hashcod () and Equals () must be able to fully determine the identity of the object
Take a look at string source
public 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;
The Hashcode calculation method in the//string class is relatively simple, with 31 as the right, and each bit to the ASCII value of the character.
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; }