Java--神奇的hashcode

1、Object的HashCode定義html

1 public native int hashCode();

  Object類的hashCode方式使用了native修飾也就意味着真正的實現調用的其餘語言編寫的方法,咱們能夠忽略具體的實現,從方法的定義上能夠看出,hashCode實際上是一個int型的整數java

  如下是hashCode()這個方法的官方解釋算法

Returns a hash code value for the object. This method is supported for the benefit of hash tables such as those provided by java.util.HashMap. 

The general contract of hashCode is: 

Whenever it is invoked on the same object more than once during an execution of a Java application, the hashCode method must consistently return the same integer, provided no information used in 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 equals(Object) method, then calling the 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 java.lang.Object.equals(java.lang.Object) method, then calling the 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 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 JavaTM programming language.)

解釋一下數組

一、hashcode()這個方法主要爲了給hash系列的集合(HashMap、HashTable、HashSet)提供支持緩存

二、一個應用在一次執行過程當中調用同一個對象的hashcode()方法返回值是同樣的,屢次執行(關閉應用再啓動)應用程序返回值可能不一致。由此推測hashcode()底層實現方法跟內存地址有關。app

三、若是兩個對象進行equals比較返回True,那麼這兩個對象的hashcode()方法必須返回一樣的值。在一些重寫equals方法的場合務必注意重寫hashcode方法以便於達到這樣的要求。關於equals的介紹能夠參照這篇文章《Java-從堆棧常量池解析equals()與==ide

四、是兩個對象equals--->hashcode相等,可是hashcode相等並不能推出兩個對象equals。緣由是hashcode的計算方法是對象的某種屬性進行的數學運算後獲得的值,不免會出現兩個不一樣的對象(equals返回false)得出同樣的hashcode(一般狀況機率極小)post

2、String對象的hashcodeui

 1  public int hashCode() {
 2         int h = hash;
 3         if (h == 0 && value.length > 0) {
 4             char val[] = value;
 5 
 6             for (int i = 0; i < value.length; i++) {
 7                 h = 31 * h + val[i];
 8             }
 9             hash = h;
10         }
11         return h;
12     }

其中hash是一個緩存,一個String對象計算過hashcode以後就不用再次計算了,由於即便是再次計算它的值仍是同樣的。value是String對象(由一個個字符構成)的字符數組this

算法其實實現了這麼一個邏輯運算:s[0]*31^(n-1) + s[1]*31^(n-2) + ... + s[n-1],n表明String的長度,簡單吧:hashcode就是一個算數運算後的int值,它通常能夠惟一標識一個對象,若是遇到兩個不一樣的對象hashcode同樣(機率很小),還要看同樣兩個對象是否equals。總之仍是能夠區分開的。

3、對象爲何要有hashcode這個屬性

  前面提到hashcode能夠給hash系列的集合提供支持,那麼也就是說hash系列的容器須要這個屬性才設置的這個屬性,那麼爲何要有hash系列的容器呢?

  容器的主要做用是存儲對象,檢索對象。一般狀況下:

  ①、Array直接經過索引檢索對象速度極快,可是Array的特色是一旦肯定容量就不能變化了

  ②、Collection,Map的之類解決了容器容量變化的問題,咱們知道他們的實現類有不少,也是各有各的特色,園子裏有位達人總結的很好參照:《Java 集合系列目錄(Category)》。

  區別主要:

  a)、Array能夠存放基本類型數據,集合類存儲的是Object

  b)、List中元素是可重複的有序的(可經過get(index)方法返回元素,Set中元素是不可重複的而且是無須的(沒法經過索引取到元素),List、Set元素是單一的,Map中的元素是key-value對

  c)、插入數據,檢索數據,修改數據三方面的效率上看能夠理解爲ArrayList基於數組實現檢索數據效率高插入修改數據效率高,LinkedList基於鏈表實現插入修改數據效率高檢索數據效率低

  d)、HashSet與TreeSet主要是有序無須的差異,後者能夠有序遍歷Set中的元素

  e)、同理HashMap與TreeMap的區別與d中所述一直由於d是基於e實現的

  ③、hash系列的容器其實主要是爲了解決了容器插入數據,檢索數據,修改數據效率折中的問題而產生的,用hashcode標識對象在集合中的位置對於排序,檢索,修改數據都較快。

相關文章
相關標籤/搜索