在Java中,Object类是所有类的父类。
今天,我们一起探讨Object类中的hashCode方法,以及hashCode在我们实际使用过程中的作用。
查看Object类hashCode源码:
/**
* Returns a hash code value for the object. This method is
* supported for the benefit of hash tables such as those provided by
* {@link java.util.HashMap}.
* <p>
* The general contract of {@code hashCode} is:
* <ul>
* <li>Whenever it is invoked on the same object more than once during
* an execution of a Java application, the {@code hashCode} method
* must consistently return the same integer, provided no information
* used in {@code equals} comparisons on the object is modified.
* This integer need not remain consistent from one execution of an
* application to another execution of the same application.
* <li>If two objects are equal according to the {@code equals(Object)}
* method, then calling the {@code hashCode} method on each of
* the two objects must produce the same integer result.
* <li>It is <em>not</em> required that if two objects are unequal
* according to the {@link java.lang.Object#equals(java.lang.Object)}
* method, then calling the {@code hashCode} method on each of the
* two objects must produce distinct integer results. However, the
* programmer should be aware that producing distinct integer results
* for unequal objects may improve the performance of hash tables.
* </ul>
* <p>
* As much as is reasonably practical, the hashCode method defined by
* class {@code Object} does return distinct integers for distinct
* objects. (This is typically implemented by converting the internal
* address of the object into an integer, but this implementation
* technique is not required by the
* Java™ programming language.)
*
* @return a hash code value for this object.
* @see java.lang.Object#equals(java.lang.Object)
* @see java.lang.System#identityHashCode
*/
public native int hashCode();
正如hashCode方法所描述的:
1.如果两个对象相等,调用hashCode方法返回的int值相等;
2.两个不相等的对象返回不同的hashCode值,有利于提高hash table的性能;
描述归描述,我们通过一个实际例子,说明hashCode如何提高hash table的性能。
Java中,关于hash table的集合类有Hashtable、HashMap、ConcurrentHashMap、LinkedHashMap,通过其中之一HashMap来说明。
HashMap中,常常使用方法get、set,查看get源码:
public V get(Object key) {
Node<K,V> e;
return (e = getNode(hash(key), key)) == null ? null : e.value;
}
static final int hash(Object key) {
int h;
return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);
}
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) {
if (first.hash == hash && // always check first node
((k = first.key) == key || (key != null && key.equals(k))))
return first;
if ((e = first.next) != null) {
if (first instanceof TreeNode)
return ((TreeNode<K,V>)first).getTreeNode(hash, key);
do {
if (e.hash == hash &&
((k = e.key) == key || (key != null && key.equals(k))))
return e;
} while ((e = e.next) != null);
}
}
return null;
}
通过一个例子了解getNode的算法,假设我们有三个房间1,2,3,每个房间都可以存储很多物品,每存储一件物品时,需要使用相同规格集装箱包装。
现在有铅笔,剪刀,橡皮,直尺,篮球,足球需要存储。
存储进房间前,在纸上记录每件物品对应的房间号。
铅笔 ——> 房间1
剪刀 ——> 房间2
橡皮 ——> 房间2
直尺 ——> 房间3
篮球 ——> 房间3
足球 ——> 房间3
所有物品都存储进对应房间,且每个物品都使用相同规格集装箱包装。
OK,现在需要取出篮球
get("篮球");
步骤:
1.在纸上找出篮球对应的房间号3(房间号3相当于篮球的hash值)
2.打开房间3,看到有三个相同的集装箱(直尺、篮球、足球),需要一个一个尝试打开,寻找出篮球。(别问我为什么还用集装箱包装,程序不是人,它需要遍历)
getNode算法大概就是步骤1,2所描述的。
从其算法可以观察到,如果直尺、篮球、足球有一一对应的房间,那么在步骤2时,打开房间,只会有一个集装箱,就不需要聚个遍历。
因此,正如hashCode源码所描述的,两个不相等的对象返回不同的hashCode值,有利于提高hash table的性能。
getNode在步骤2时,有两种方式去寻找集装箱,一种是线性链表,一种红黑树。//TODO,后续会超链接线性链表、红黑树
总结
hashCode的作用
1.如果两个对象相等,调用hashCode方法返回的int值相等;
2.两个不相等的对象返回不同的hashCode值,有利于提高hash table的性能;
hashCode.getNode算法
1.在纸上寻找房间号;
2.对应房间里遍历集装箱;
网友评论