探讨hashCode

在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}.
     * 

* The general contract of {@code hashCode} is: *

    *
  • 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. *
  • 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. *
  • It is not 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. *
*

* 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 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 getNode(int hash, Object key) {
        Node[] tab; Node 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)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.对应房间里遍历集装箱;

你可能感兴趣的:(探讨hashCode)