老熟女激烈的高潮_日韩一级黄色录像_亚洲1区2区3区视频_精品少妇一区二区三区在线播放_国产欧美日产久久_午夜福利精品导航凹凸

Java中HashMap的實現(xiàn)原理是什么

這篇文章將為大家詳細講解有關Java中HashMap的實現(xiàn)原理是什么,文章內(nèi)容質(zhì)量較高,因此小編分享給大家做個參考,希望大家閱讀完這篇文章后對相關知識有一定的了解。

創(chuàng)新互聯(lián)公司主要從事做網(wǎng)站、成都做網(wǎng)站、網(wǎng)頁設計、企業(yè)做網(wǎng)站、公司建網(wǎng)站等業(yè)務。立足成都服務隆回,10年網(wǎng)站建設經(jīng)驗,價格優(yōu)惠、服務專業(yè),歡迎來電咨詢建站服務:18982081108

一、Java中的HashCode 和equals

  • 關于hashcode

    1、hashcode的存在主要是用于查找的快捷性,如Hashtable,HashMap等,hashCode是用來在散列存儲結(jié)構(gòu)中確定對象的存儲地址的。

    2、如果兩個對象相同,就是適用于equals(java.lang.Object)方法,那么這個兩個對象的hashCode一定要相同。

    3、如果對象的equals方法被重寫,那么對象的hashCode也盡量重寫,并且產(chǎn)生hashCode使用的對象,一定要和equals方法中使用的一致,否則就會違反上面提到的第二點

    4、兩個對象的hashCode相同,并不一定表示兩個對象就相同,也就是不一定適用于equals(java.lang.Object)方法,只能夠說明這兩個對象在散列存儲結(jié)構(gòu)中,如Hashtable.他們存放在同一個籃子里

hashCode 用于查找使用的,equals是用于比較兩個對象是否相等。

  • 關于equals

    1、equals 和 ==

==用于比較引用和比較基本數(shù)據(jù)類型時具有不同的功能:

比較基本數(shù)據(jù)類型,如果兩個值相同,則結(jié)果為true

而在比較引用時,如果引用指向內(nèi)存中的同一對象,結(jié)果為true;

equals()作為方法,實現(xiàn)對象的比較。由于==運算符不允許我們進行覆蓋,也就是說它限制了我們的表達。因此我們復寫(重寫,子類復寫)equals方法,達到比較對象內(nèi)容是否相同的目的。而這些通過==運算符是做不到的。

    2、Object類的equals()方法的比較規(guī)則為:如果兩個對象的類型一致,并且內(nèi)容一致,則返回true,這些類有:

java.io.file,java.util.Date,java.lang.string,包裝類(Integer,Double等)

二、HashMap的實現(xiàn)原理

1、HashMap概述

HashMap是基于哈希表的Map接口的非同步實現(xiàn)。此實現(xiàn)提供所有可選的映射操作,并允許使用null值和null鍵。此類不保證映射的順序,特別是它不保證該順序恒久不變。

在Java編程語言中,最基本的結(jié)構(gòu)就是兩種,一種是數(shù)組,另一個是模擬指針(引用),所有的數(shù)據(jù)結(jié)構(gòu)都可以用這兩個基本結(jié)構(gòu)來構(gòu)造,HashMap也不列外。HashMap也不例外。HashMap實際上是一個鏈表散列的數(shù)據(jù)結(jié)構(gòu),即數(shù)組和鏈表的結(jié)合體。

Java中HashMap的實現(xiàn)原理是什么

從上圖中可以看出,HashMap底層就是一個數(shù)組結(jié)構(gòu),數(shù)組中的每一項又是一個鏈表。當新建一個HashMap的時候,就會初始化一個數(shù)組。

/**
 * Basic hash bin node, used for most entries.  (See below for
 * TreeNode subclass, and in LinkedHashMap for its Entry subclass.)
 */
static class Node implements Map.Entry {
    final int hash;
    final K key;
    V value;
    Node next;

    Node(int hash, K key, V value, Node next) {
        this.hash = hash;
        this.key = key;
        this.value = value;
        this.next = next;
    }

    public final K getKey()        { return key; }
    public final V getValue()      { return value; }
    public final String toString() { return key + "=">可以看出,Node就是數(shù)組中的元素,每個 Map.Entry 其實就是一個key-value對,它持有一個指向下一個元素的引用,這就構(gòu)成了鏈表 2、HashMap實現(xiàn)存儲和讀取1)存儲/**
 * Associates the specified value with the specified key in this map.
 * If the map previously contained a mapping for the key, the old
 * value is replaced.
 *
 * @param key key with which the specified value is to be associated
 * @param value value to be associated with the specified key
 * @return the previous value associated with key, or
 *         null if there was no mapping for key.
 *         (A null return can also indicate that the map
 *         previously associated null with key.)
 */
public V put(K key, V value) {
    return putVal(hash(key), key, value, false, true);
}

/**
 * Implements Map.put and related methods
 *
 * @param hash hash for key
 * @param key the key
 * @param value the value to put
 * @param onlyIfAbsent if true, don't change existing value
 * @param evict if false, the table is in creation mode.
 * @return previous value, or null if none
 */
final V putVal(int hash, K key, V value, boolean onlyIfAbsent,
               boolean evict) {
    Node[] tab; Node p; int n, i;
    if ((tab = table) == null || (n = tab.length) == 0)
        n = (tab = resize()).length;
    if ((p = tab[i = (n - 1) & hash]) == null)
        tab[i] = newNode(hash, key, value, null);
    else {
        Node e; K k;
        if (p.hash == hash &&
            ((k = p.key) == key || (key != null && key.equals(k))))
            e = p;
        else if (p instanceof TreeNode)
            e = ((TreeNode)p).putTreeVal(this, tab, hash, key, value);
        else {
            for (int binCount = 0; ; ++binCount) {
                if ((e = p.next) == null) {
                    p.next = newNode(hash, key, value, null);
                    if (binCount >= TREEIFY_THRESHOLD - 1) // -1 for 1st
                        treeifyBin(tab, hash);
                    break;
                }
                if (e.hash == hash &&
                    ((k = e.key) == key || (key != null && key.equals(k))))
                    break;
                p = e;
            }
        }
        if (e != null) { // existing mapping for key
            V oldValue = e.value;
            if (!onlyIfAbsent || oldValue == null)
                e.value = value;
            afterNodeAccess(e);
            return oldValue;
        }
    }
    ++modCount;
    if (++size > threshold)
        resize();
    afterNodeInsertion(evict);
    return null;
} 根據(jù)hash值得到這個元素在數(shù)組中的位置(即下標),如果數(shù)組該位置上已經(jīng)存放有其他元素了,那么在這個位置上的元素將以鏈表的形式存放,新加入的放在鏈頭,最先加入的放在鏈尾。如果數(shù)組該位置上沒有元素,就直接將該元素放到此數(shù)組中的該位置上。/**
 * Computes key.hashCode() and spreads (XORs) higher bits of hash
 * to lower.  Because the table uses power-of-two masking, sets of
 * hashes that vary only in bits above the current mask will
 * always collide. (Among known examples are sets of Float keys
 * holding consecutive whole numbers in small tables.)  So we
 * apply a transform that spreads the impact of higher bits
 * downward. There is a tradeoff between speed, utility, and
 * quality of bit-spreading. Because many common sets of hashes
 * are already reasonably distributed (so don't benefit from
 * spreading), and because we use trees to handle large sets of
 * collisions in bins, we just XOR some shifted bits in the
 * cheapest possible way to reduce systematic lossage, as well as
 * to incorporate impact of the highest bits that would otherwise
 * never be used in index calculations because of table bounds.
 */
static final int hash(Object key) {
    int h;
    return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);
} 我們可以看到在hashMap中要找到某個元素,需要根據(jù)key的hash值來求得對應數(shù)組中的位置。如何計算這個位置就是hash算法。前面的說過HashMap的數(shù)據(jù)結(jié)構(gòu)是數(shù)組和鏈表的結(jié)合,所以我們希望這個HashMap里面的元素位置盡量的分布均勻些。盡量使得每個位置上的元素數(shù)量只有一個,那么當我們用hash算法求得這個位置時,馬上就可以知道對應位置的元素都是我們要的,而不用再去遍歷鏈表,這就大大優(yōu)化了查詢效率。HashMap 在底層將 key-value 當成一個整體進行處理,這個整體就是一個 Node 對象。HashMap 底層采用一個 Node[] 數(shù)組來保存所有的 key-value 對,當需要存儲一個 Node 對象時,會根據(jù)hash算法來決定其在數(shù)組中的存儲位置,在根據(jù)equals方法決定其在該數(shù)組位置上的鏈表中的存儲位置;當需要取出一個Entry時,也會根據(jù)hash算法找到其在數(shù)組中的存儲位置,再根據(jù)equals方法從該位置上的鏈表中取出該Node。3、HashMap的resize    當hashmap的元素越來越多的時候,碰撞的概率就越來越高(因為數(shù)組的長度是固定的),所以為了提高查詢的效率,就要對hashMap的數(shù)組進行擴容,數(shù)組擴容這個操作也會出現(xiàn)在ArrayList中,所以這是一個通用的操作,類似均攤。hashmap擴容之后,最消耗性能的點就出現(xiàn)了:原數(shù)組中的數(shù)據(jù)必須重新計算其在新數(shù)組中的位置,并放進去,就是resize。    那么hashmap什么時候擴容?當hashmap中的元素個數(shù)超過數(shù)組大小*loadFactor時,就會進行數(shù)組擴容,loadFactor的默認值為0.75,也就是說,默認情況下,數(shù)組大小為16,那么當hashmap中元素個數(shù)超過16*0.75=12的時候,就把數(shù)組的大小擴展為2*16=32,即擴大一倍,然后重新計算每個元素在新數(shù)組中的位置,放進去,就是resize。總結(jié):HashMap的實現(xiàn)原理:    1、實現(xiàn)key的hashCode重新hash計算出當前對象的元素在數(shù)組中的下標。    2、存儲時,如果出現(xiàn)hash值相同的key,此時有兩種情況。(1)如果key相同,則覆蓋原始值;(2)如果key不同(出現(xiàn)沖突),則將當前的key-value放入鏈表中    3、獲取時,直接找hash值對應的下標,在進一步判斷key是否相同,從而找到對應值。    4、理解以上過程就不難明白HashMap是如何解決hash沖突的問題,核心就是使用了數(shù)組的存儲方式,然后將沖突的key的對象放入鏈表中,一旦發(fā)現(xiàn)沖突就在鏈表中做進一步的對比。

關于Java中HashMap的實現(xiàn)原理是什么就分享到這里了,希望以上內(nèi)容可以對大家有一定的幫助,可以學到更多知識。如果覺得文章不錯,可以把它分享出去讓更多的人看到。


網(wǎng)頁題目:Java中HashMap的實現(xiàn)原理是什么
URL分享:http://www.xueling.net.cn/article/peodch.html

其他資訊

在線咨詢
服務熱線
服務熱線:028-86922220
TOP
主站蜘蛛池模板: 欧美高大丰满freesex | 91综合中文字幕乱偷在线 | 91免费国产精品 | 中国老太卖婬HD播放 | 又粗又大又硬毛片免费看 | 91五月色国产在线观看 | 国产在线无码永久免费 | sese亚洲 | 中文av在线播放 | 在线播放黄色网址 | 奇米影视小说 | 成www日本在线观看 成人综合婷婷国产精品久久蜜臀 | 国产精品久久人妻无码免费看 | 96精品在线观看 | 国产美女操b在线观看 | 亚洲国产av无码精品 | 无码免费H成年动漫在线观看网站 | 精品久久久999 | 美女黄色a级 | 亚洲视频1区2区3区4区 | 丰满少妇人妻HD高清大乳 | tube性老少配bbwcom | 国产一区二区三区中文 | 国产成人在线免费观看视频 | 国产无遮挡无码裸体视频在现观看 | 全免费a级毛片免费看视频免费下 | 亚洲JIZZJIZZ中国少妇中文 | 久久精品一区二区三区四区毛片 | 91欧美一区二区三区 | 看日本黄色大片 | 日韩a级毛片免费观看 | 人妻精品久久无码专区精东影业 | 亚洲国产一区二区三区a毛片 | 免费观看日本污污ww网站 | 中文字幕AV一区乱码 | a级毛片免费在线播放 | 超碰97免费观看 | 成人特级片 | 久久网中文字幕 | 美女自慰喷水在线观看 | 国内av在线播放 |