hashcode & equals
Hashcode and equals are important in the hash structure, with the former used for quick positioning and the latter for comparing replacements
The standard writing of Hashcode
override fun hashCode(a): Int {
// The benefits of using 31: the VM automatically converts it into bit operations (CPU supported operations), which is faster
var result = sourceKey.hashCode()
result += 31 * result + signature.hashCode()
result += 31 * result + width
result += 31* result + height appliedTransformation? .let { result +=31 * result + it.hashCode()
}
result += 31 * result + decodedResourceClass.hashCode()
result += 31 * result + options.hashCode()
return result
}
Copy the code
Equals
override fun equals(o: Any?).: Boolean {
if (o is ResourceCacheKey) {
return o.let {
// Kotlin == = Java equals
return sourceKey == it.sourceKey &&
signature == it.signature &&
width == it.width &&
height == it.height &&
appliedTransformation == it.appliedTransformation &&
decodedResourceClass == it.decodedResourceClass &&
options == it.options
}
}
return false
}
Copy the code
Analysis of PUT method
A flowchart
- Use hashcode to calculate the location in the hash table
- If no node exists in this location, create a node to store the value
- There are nodes at this location, and conflicts are handled through the equals method
public V put(K key, V value) {
return putVal(hash(key), key, value, false.true);
}
//onlyIfAbsent =false
final V putVal(int hash, K key, V value, boolean onlyIfAbsent,
boolean evict) {
Node<K,V>[] tab; Node<K,V> p; int n, i;
// If the table is empty, create the table using the resize method
if ((tab = table) == null || (n = tab.length) == 0)
n = (tab = resize()).length;
// Obtain index in the table by (n-1) &hash
if ((p = tab[i = (n - 1) & hash]) == null)
// If the current location has no value, create a new node to store the value
tab[i] = newNode(hash, key, value, null);
else {
// If there is a value in the current position, conflicts are handled through equals
Node<K,V> e; K k;
if(p.hash == hash && ((k = p.key) == key || (key ! =null && key.equals(k))))
// Hash is calculated from hashcode, so hashcode is equal and equals is equal
// Then point e to p for later replacement of value
e = p;
else if (p instanceof TreeNode)
// If hashcode is equal,equals is unequal
// Store in the red-black tree
e = ((TreeNode<K,V>)p).putTreeVal(this, tab, hash, key, value);
else {
// If hashcode is equal,equals is unequal
// Iterate through the list
for (int binCount = 0; ; ++binCount) {
// Iterate to the end of the list
if ((e = p.next) == null) {
// Create a Node at the end of the list to store the Node
p.next = newNode(hash, key, value, null);
//TREEIFY_THRESHOLD defaults to 8;
if (binCount >= TREEIFY_THRESHOLD - 1) // -1 for 1st
// If there are more than 8 nodes, tree the nodes
treeifyBin(tab, hash);
break;
}
// if equals equals, break and replace with new value
if(e.hash == hash && ((k = e.key) == key || (key ! =null && key.equals(k))))
break; p = e; }}// Replace the new value
if(e ! =null) { // existing mapping for key
V oldValue = e.value;
if(! onlyIfAbsent || oldValue ==null)
//onlyIfAbsent =false, replace value with new value
e.value = value;
afterNodeAccess(e);
// Return oldValue
return oldValue;
}
}
++modCount;
if (++size > threshold)
// If the size is larger than the threshold, expand the capacity
resize();
afterNodeInsertion(evict);
return null;
}
Copy the code
Analysis of GET method
A flowchart
- Calculate the position index in the table by hashcode
- Iterates over a single linked list or a red-black tree, returning value if equals equals equals
public V get(Object key) {
Node<K,V> e;
return (e = getNode(hash(key), key)) == null ? null : e.value;
}
final Node<K,V> getNode(int hash, Object key) {
Node<K,V>[] tab; Node<K,V> first, e; int n; K k;
if((tab = table) ! =null && (n = tab.length) > 0 &&
(first = tab[(n - 1) & hash]) ! =null) {
Hash = (n-1) &hash = (n-1) &hash = (n-1)
if(first.hash == hash && ((k = first.key) == key || (key ! =null && key.equals(k))))
// If first equals equals, first is returned
return first;
// Handle conflict situations
if((e = first.next) ! =null) {
// Iterates through the red and black tree to find equals elements and returns
if (first instanceof TreeNode)
return ((TreeNode<K,V>)first).getTreeNode(hash, key);
// Iterates through the list to find equals elements and returns them
do {
if(e.hash == hash && ((k = e.key) == key || (key ! =null && key.equals(k))))
return e;
} while((e = e.next) ! =null); }}return null;
}
Copy the code
conclusion
- Put: Locate the conflict using Hashcode, and then handle the conflict through equals. If eqauls are equal, replace the old value with the new value, and if not, store the conflict with a linked list or red-black tree
- Get: Locate by hashcode and find the equals value