Hash和HashCode深入理解

目錄介紹

  • 1.Hash的作用介紹
    • 1.1 Hash的定義
    • 1.2 Hash函數(shù)特性
    • 1.3 Hash的使用場景
  • 2.如何判斷兩個(gè)對象相等
    • 2.1 判斷兩個(gè)字符串
    • 2.2 判斷兩個(gè)int數(shù)值
    • 2.3 其他基本類型
  • 3.HashCode深入分析
    • 3.0 HashCode是什么
    • 3.1 為什么要重寫HashCode
    • 3.2 HashCode源代碼分析
    • 3.3 HashCode帶來的疑問
    • 3.4 HashCode的作用
    • 3.5 HashMap中的HashCode
    • 3.6 可直接用hashcode判斷兩個(gè)對象是否相等
  • 4.Hash表是什么
    • 4.1 Hash表定義
    • 4.2 Hash表簡單介紹
  • 5.Hash中的算法應(yīng)用
    • 5.1 基礎(chǔ)算法
    • 5.2 經(jīng)典算法[摘自網(wǎng)絡(luò)]
    • 5.3 Hash碰撞[摘自網(wǎng)絡(luò)]
  • 6.Hash在Java中的應(yīng)用場景
    • 6.1 equals與hashCode有兩個(gè)注意點(diǎn)
    • 6.2 以HashSet為例說明hashCode()的作用
    • 6.3 以HashMap為例說明Hash的作用
    • 6.4
  • 7.版本更新情況
  • 8.其他介紹

好消息

  • 博客筆記大匯總【16年3月到至今】稻薇,包括Java基礎(chǔ)及深入知識點(diǎn)胶征,Android技術(shù)博客睛低,Python學(xué)習(xí)筆記等等钱雷,還包括平時(shí)開發(fā)中遇到的bug匯總,當(dāng)然也在工作之余收集了大量的面試題拉庵,長期更新維護(hù)并且修正套蒂,持續(xù)完善……開源的文件是markdown格式的操刀!同時(shí)也開源了生活博客,從12年起撼嗓,積累共計(jì)47篇[近20萬字]静稻,轉(zhuǎn)載請注明出處,謝謝杀迹!
  • 鏈接地址:https://github.com/yangchong211/YCBlogs
  • 如果覺得好押搪,可以star一下大州,謝謝厦画!當(dāng)然也歡迎提出建議,萬事起于忽微力试,量變引起質(zhì)變排嫌!

1.Hash的作用介紹

1.1 Hash的定義

  • 散列(哈希)函數(shù)
    • 把任意長度的輸入(又叫做預(yù)映射pre-image)通過散列算法變換成固定長度的輸出淳地,該輸出就是散列值颇象,是一種壓縮映射。
    • 或者說一種將任意長度的消息壓縮到某一固定長度的消息摘要的函數(shù)嚷缭。

1.2 Hash函數(shù)特性

  • h(k1)≠h(k2)則k1≠k2,即散列值不相同路幸,則輸入值即預(yù)映射不同
    • 如果k1≠k2简肴,h(k1)=h(k2) 則發(fā)生碰撞;
    • 如果h(k1)=h(k2)能扒,k1不一定等于k2初斑;

1.3 Hash的使用場景

  • 比如說我們下載一個(gè)文件见秤,文件的下載過程中會經(jīng)過很多網(wǎng)絡(luò)服務(wù)器、路由器的中轉(zhuǎn)乎澄,如何保證這個(gè)文件就是我們所需要的呢测摔?我們不可能去一一檢測這個(gè)文件的每個(gè)字節(jié)锋八,也不能簡單地利用文件名查库、文件大小這些極容易偽裝的信息,這時(shí)候整慎,就需要一種指紋一樣的標(biāo)志來檢查文件的可靠性裤园,這種指紋就是我們現(xiàn)在所用的Hash算法(也叫散列算法)剂府。
  • 散列算法就是一種以較短的信息來保證文件唯一性的標(biāo)志腺占,這種標(biāo)志與文件的每一個(gè)字節(jié)都相關(guān),而且難以找到逆向規(guī)律铡羡。因此烦周,當(dāng)原有文件發(fā)生改變時(shí),其標(biāo)志值也會發(fā)生改變漱贱,從而告訴文件使用者當(dāng)前的文件已經(jīng)不是你所需求的文件幅狮。
  • 這種標(biāo)志有何意義呢闰靴?之前文件下載過程就是一個(gè)很好的例子蚂且,事實(shí)上杏死,現(xiàn)在大部分的網(wǎng)絡(luò)部署和版本控制工具都在使用散列算法來保證文件可靠性。

2.如何判斷兩個(gè)對象相等

2.1 判斷兩個(gè)字符串

  • 使用equals方法判斷兩個(gè)字符串是否相等
String a = "yc1";
String b = "yc2";
boolean isEqual = a.equals(b);
  • 當(dāng)然Object的子類可以通過重寫equals的方法腐巢,實(shí)現(xiàn)子類自身的對象是否相等的邏輯冯丙;String是Object的子類胃惜,查看下它的equals方法
//在Object類中
public boolean equals(Object obj) {
    //直接比較的是地址
    return (this == obj);
}

//在String類中
public boolean equals(Object anObject) {
    //直接比較的是地址
    if (this == anObject) {
        return true;
    }
    //盤旋是否是字符串String類型
    if (anObject instanceof String) {
        String anotherString = (String) anObject;
        int n = count;
        if (n == anotherString.count) {
            int i = 0;
            //循環(huán)判斷每個(gè)字符是否相等
            while (n-- != 0) {
                if (charAt(i) != anotherString.charAt(i))
                        return false;
                i++;
            }
            return true;
        }
    }
    return false;
}

2.2 判斷兩個(gè)int數(shù)值

  • Integer類的equals方法又是如何實(shí)現(xiàn)的呢船殉?
Integer a = Integer.valueOf("1");
Integer b = Integer.valueOf("2");
boolean ab = a.equals(b);


public boolean equals(Object obj) {
    //先判斷是否是Integer類型
    if (obj instanceof Integer) {
        //轉(zhuǎn)為int值后進(jìn)行比較
        return value == ((Integer)obj).intValue();
    }
    return false;
}

2.3 其他基本類型

//short類型
@Override
public int hashCode() {
    return Short.hashCode(value);
}
public static int hashCode(short value) {
    return (int)value;
}


//Byte類型
@Override
public int hashCode() {
    return Byte.hashCode(value);
}
public static int hashCode(byte value) {
    return (int)value;
}

//Long類型
@Override
public int hashCode() {
    return Long.hashCode(value);
}
public static int hashCode(long value) {
    return (int)(value ^ (value >>> 32));
}
//long類型作為索引范圍太大利虫,需要轉(zhuǎn)為int類型糠惫。這里簡單的獲取低32位容易導(dǎo)致散列不均钉疫,因?yàn)楦呶徊糠譀]有被利用陌选。所以這里采用邏輯右移32位咨油,讓高32位和低32位進(jìn)行XOR操作,導(dǎo)致高位低位都能被利用到

//Boolean類型
@Override
public int hashCode() {
    return Boolean.hashCode(value);
}
public static int hashCode(boolean value) {
    return value ? 1231 : 1237;
}
//采用兩個(gè)質(zhì)數(shù)作為true或false的索引赚爵。這兩個(gè)質(zhì)數(shù)足夠大冀膝,用來作為索引時(shí)霎挟,出現(xiàn)碰撞的可能性低酥夭。


3.HashCode深入分析

3.0 HashCode是什么

  • HashCode是Object的一個(gè)方法熬北,hashCode方法返回一個(gè)hash code值讶隐,且這個(gè)方法是為了更好的支持hash表,比如String效五,Set火俄,HashTable讲冠、HashMap等;

3.1 為什么要重寫HashCode

  • 如果用 equal 去比較的話竿开,如果存在1000個(gè)元素否彩,你 new 一個(gè)新的元素出來,需要去調(diào)用1000次equal去逐個(gè)和他們比較是否是同一個(gè)對象敬尺,這樣會大大降低效率砂吞。hashcode實(shí)際上是返回對象的存儲地址蜻直,如果這個(gè)位置上沒有元素,就把元素直接存儲在上面呼巷,如果這個(gè)位置上已經(jīng)存在元素王悍,這個(gè)時(shí)候才去調(diào)用equal方法與新元素進(jìn)行比較配名,相同的話就不存了晋辆,散列到其他地址上

3.2 HashCode源代碼分析

  • 在Object中的HashCode源代碼
public int hashCode() {
    int lockWord = shadow$_monitor_;
    final int lockWordStateMask = 0xC0000000; // Top 2 bits.
    final int lockWordStateHash = 0x80000000; // Top 2 bits are value 2 (kStateHash).
    final int lockWordHashMask = 0x0FFFFFFF; // Low 28 bits.
    if ((lockWord & lockWordStateMask) == lockWordStateHash) {
        return lockWord & lockWordHashMask;
    }
    //返回的是對象引用地址
    return System.identityHashCode(this);
}
  • 在String中的HashCode源代碼
public int hashCode() {
    int h = hash;
    if (h == 0 && count > 0) {
        for (int i = 0; i < count; i++) {
            h = 31 * h + charAt(i);
        }
        hash = h;
    }
    return h;
}
  • 在Integer中的HashCode源代碼
public int hashCode() {
    //int值
    return value;
}

3.3 HashCode帶來的疑問

  • 為何重寫equals建議同時(shí)重寫hashCode芋膘?
  • hashCode是什么为朋?
  • hashCode作用厚脉?
  • hash code(hash值)是什么傻工?
  • hash table(hash表)是什么中捆?
  • hashCode方法對hash表有益處?
  • hashCode方法對不是hash有益處嗎?

3.4 HashCode的作用

  • 減少查找次數(shù)殴蓬,提高程序效率
    • 例如查找是否存在重復(fù)值
      • h(k1)≠h(k2)則k1≠k2
      • 首先查看h(k2)輸出值(內(nèi)存地址)染厅,查看該內(nèi)存地址是否存在值肖粮;
      • 如果無尿赚,則表示該值不存在重復(fù)值蕉堰;
      • 如果有屋讶,則進(jìn)行值比較,相同則表示該值已經(jīng)存在散列列表中斩芭,如果不相同則再進(jìn)行一個(gè)一個(gè)值比較划乖;而無需一開始就一個(gè)一個(gè)值的比較琴庵,減少了查找次數(shù)

3.5 HashMap中的HashCode

  • 在Java中也一樣迷殿,hashCode方法的主要作用是為了配合基于散列的集合一起正常運(yùn)行咖杂,這樣的散列集合包括HashSet诉字、HashMap以及HashTable奏窑。
  • 為什么這么說呢导披?考慮一種情況,當(dāng)向集合中插入對象時(shí)埃唯,如何判別在集合中是否已經(jīng)存在該對象了撩匕?(注意:集合中不允許重復(fù)的元素存在)
    • 也許大多數(shù)人都會想到調(diào)用equals方法來逐個(gè)進(jìn)行比較,這個(gè)方法確實(shí)可行墨叛。但是如果集合中已經(jīng)存在一萬條數(shù)據(jù)或者更多的數(shù)據(jù)止毕,如果采用equals方法去逐一比較模蜡,效率必然是一個(gè)問題。
    • 此時(shí)hashCode方法的作用就體現(xiàn)出來了忍疾,當(dāng)集合要添加新的對象時(shí),先調(diào)用這個(gè)對象的hashCode方法谨朝,得到對應(yīng)的hashcode值卤妒,實(shí)際上在HashMap的具體實(shí)現(xiàn)中會用一個(gè)table保存已經(jīng)存進(jìn)去的對象的hashcode值,如果table中沒有該hashcode值字币,它就可以直接存進(jìn)去则披,不用再進(jìn)行任何比較了;如果存在該hashcode值洗出, 就調(diào)用它的equals方法與新元素進(jìn)行比較士复,相同的話就不存了,不相同就散列其它的地址翩活,所以這里存在一個(gè)沖突解決的問題阱洪,這樣一來實(shí)際調(diào)用equals方法的次數(shù)就大大降低了,說通俗一點(diǎn):Java中的hashCode方法就是根據(jù)一定的規(guī)則將與對象相關(guān)的信息(比如對象的存儲地址菠镇,對象的字段等)映射成一個(gè)數(shù)值冗荸,這個(gè)數(shù)值稱作為散列值。下面這段代碼是java.util.HashMap的中put方法的具體實(shí)現(xiàn):
  • put方法是用來向HashMap中添加新的元素利耍,從put方法的具體實(shí)現(xiàn)可知俏竞,會先調(diào)用hashCode方法得到該元素的hashCode值,然后查看table中是否存在該hashCode值堂竟,如果存在則調(diào)用equals方法重新確定是否存在該元素魂毁,如果存在,則更新value值出嘹,否則將新的元素添加到HashMap中席楚。從這里可以看出,hashCode方法的存在是為了減少equals方法的調(diào)用次數(shù)税稼,從而提高程序效率烦秩。
public V put(K key, V value) {
    return putVal(hash(key), key, value, false, true);
}

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 ((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<K,V> 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<K,V>)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;
}

3.6 可直接用hashcode判斷兩個(gè)對象是否相等

  • 肯定是不可以的,因?yàn)椴煌膶ο罂赡軙上嗤膆ashcode值郎仆。雖然不能根據(jù)hashcode值判斷兩個(gè)對象是否相等只祠,但是可以直接根據(jù)hashcode值判斷兩個(gè)對象不等,如果兩個(gè)對象的hashcode值不等扰肌,則必定是兩個(gè)不同的對象抛寝。如果要判斷兩個(gè)對象是否真正相等,必須通過equals方法。
  • 也就是說對于兩個(gè)對象盗舰,如果調(diào)用equals方法得到的結(jié)果為true晶府,則兩個(gè)對象的hashcode值必定相等;
    • 如果equals方法得到的結(jié)果為false钻趋,則兩個(gè)對象的hashcode值不一定不同川陆;
    • 如果兩個(gè)對象的hashcode值不等,則equals方法得到的結(jié)果必定為false蛮位;
    • 如果兩個(gè)對象的hashcode值相等较沪,則equals方法得到的結(jié)果未知。

4.Hash表是什么

4.1 Hash表定義

  • 根據(jù)關(guān)鍵碼值(KEY-VALUE)而直接進(jìn)行訪問的數(shù)據(jù)結(jié)構(gòu)失仁;它通過把關(guān)鍵碼值(KEY-VALUE)映射到表中一個(gè)位置來訪問記錄购对,以加快查找的速度。這個(gè)映射函數(shù)叫做散列函數(shù)陶因,存放記錄的數(shù)組叫做散列表。

4.2 Hash表簡單介紹

  • 將k作為輸入值垂蜗,h(k)輸出值作為內(nèi)存地址楷扬,該內(nèi)存地址用來存放value,然后可以通過k獲取到value存放的地址贴见,從而獲取value信息烘苹。

5.Hash中的算法應(yīng)用

5.1 基礎(chǔ)算法

  • 比如,Java中的String.hashCode使用乘法和加法
public int hashCode() {
    int h = hash;
    if (h == 0 && count > 0) {
        for (int i = 0; i < count; i++) {
            //乘法與加法
            h = 31 * h + charAt(i);
        }
        hash = h;
    }
    return h;
}

5.2 經(jīng)典算法[摘自網(wǎng)絡(luò)]

  • MD4片部,MD5镣衡,SHA-1或SHA-2等其他

5.3 Hash碰撞[摘自網(wǎng)絡(luò)]

  • hash是存在碰撞的,如果k1≠k2档悠,h(k1)=h(k2) 則發(fā)生碰撞廊鸥;

6.Hash在Java中的應(yīng)用場景

6.1 equals與hashCode有兩個(gè)注意點(diǎn)

  • equals相同,則hashCode相同辖所;而hashCode相同惰说,equals不一定相同
    • 如果equals相同,hashCode不相同缘回,有可能會造成上述重復(fù)值等情況吆视,這種情況是不允許的;
    • 而hasCode相同酥宴,但是equals不一定相同啦吧,有可能是因?yàn)榘l(fā)生了碰撞而碰撞是有可能性發(fā)生的

6.2 以HashSet為例說明hashCode()的作用

  • 假設(shè),HashSet中已經(jīng)有1000個(gè)元素拙寡。當(dāng)插入第1001個(gè)元素時(shí)授滓,需要怎么處理?
    • 因?yàn)镠ashSet是Set集合,它允許有重復(fù)元素褒墨§潘ⅲ“將第1001個(gè)元素逐個(gè)的和前面1000個(gè)元素進(jìn)行比較”?
    • 顯然郁妈,這個(gè)效率是相等低下的浑玛。散列表很好的解決了這個(gè)問題,它根據(jù)元素的散列碼計(jì)算出元素在散列表中的位置噩咪,然后將元素插入該位置即可顾彰。對于相同的元素,自然是只保存了一個(gè)胃碾。
    • 由此可知涨享,若兩個(gè)元素相等,它們的散列碼一定相等仆百;但反過來確不一定食磕。在散列表中怕敬,
      • 1、如果兩個(gè)對象相等,那么它們的hashCode()值一定要相同歉提;
      • 2粥庄、如果兩個(gè)對象hashCode()相等份乒,它們并不一定相等腿堤。
      • 注意:這是在散列表中的情況。在非散列表中一定如此波势!

6.3 以HashMap為例說明Hash的作用

  • 在HashMap中有許多地方用到了hash算法
//put方法
public V put(K key, V value) {
    return putVal(hash(key), key, value, false, true);
}

//remove方法
public V remove(Object key) {
    Node<K,V> e;
    return (e = removeNode(hash(key), key, null, false, true)) == null ?
        null : e.value;
}

//get方法
public V get(Object key) {
    Node<K,V> e;
    return (e = getNode(hash(key), key)) == null ? null : e.value;
}

//上面這幾個(gè)方法都用到了這個(gè)方法
static final int hash(Object key) {
    int h;
    //計(jì)算hashCode翎朱,并無符號移動到低位
    return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);
}

舉個(gè)例子: h = 363771819^(363771819 >>> 16)
0001 0101 1010 1110 1011 0111 1010 1011(363771819)
0000 0000 0000 0000 0001 0101 1010 1110(5550) XOR
--------------------------------------- =
0001 0101 1010 1110 1010 0010 0000 0101(363766277)
這樣做可以實(shí)現(xiàn)了高地位更加均勻地混到一起

參考博客

關(guān)于其他內(nèi)容介紹

01.關(guān)于博客匯總鏈接

02.關(guān)于我的博客

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末尺铣,一起剝皮案震驚了整個(gè)濱河市拴曲,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌凛忿,老刑警劉巖疗韵,帶你破解...
    沈念sama閱讀 206,968評論 6 482
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異侄非,居然都是意外死亡蕉汪,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,601評論 2 382
  • 文/潘曉璐 我一進(jìn)店門逞怨,熙熙樓的掌柜王于貴愁眉苦臉地迎上來者疤,“玉大人,你說我怎么就攤上這事叠赦【月恚” “怎么了革砸?”我有些...
    開封第一講書人閱讀 153,220評論 0 344
  • 文/不壞的土叔 我叫張陵,是天一觀的道長糯累。 經(jīng)常有香客問我算利,道長,這世上最難降的妖魔是什么泳姐? 我笑而不...
    開封第一講書人閱讀 55,416評論 1 279
  • 正文 為了忘掉前任效拭,我火速辦了婚禮,結(jié)果婚禮上胖秒,老公的妹妹穿的比我還像新娘缎患。我一直安慰自己,他們只是感情好阎肝,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,425評論 5 374
  • 文/花漫 我一把揭開白布挤渔。 她就那樣靜靜地躺著,像睡著了一般风题。 火紅的嫁衣襯著肌膚如雪判导。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,144評論 1 285
  • 那天沛硅,我揣著相機(jī)與錄音眼刃,去河邊找鬼。 笑死稽鞭,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的引镊。 我是一名探鬼主播朦蕴,決...
    沈念sama閱讀 38,432評論 3 401
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼弟头!你這毒婦竟也來了吩抓?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,088評論 0 261
  • 序言:老撾萬榮一對情侶失蹤赴恨,失蹤者是張志新(化名)和其女友劉穎疹娶,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體伦连,經(jīng)...
    沈念sama閱讀 43,586評論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡雨饺,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,028評論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了惑淳。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片额港。...
    茶點(diǎn)故事閱讀 38,137評論 1 334
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖歧焦,靈堂內(nèi)的尸體忽然破棺而出移斩,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 33,783評論 4 324
  • 正文 年R本政府宣布向瓷,位于F島的核電站肠套,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏猖任。R本人自食惡果不足惜你稚,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,343評論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望超升。 院中可真熱鬧入宦,春花似錦、人聲如沸室琢。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,333評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽盈滴。三九已至涯肩,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間巢钓,已是汗流浹背病苗。 一陣腳步聲響...
    開封第一講書人閱讀 31,559評論 1 262
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留症汹,地道東北人硫朦。 一個(gè)月前我還...
    沈念sama閱讀 45,595評論 2 355
  • 正文 我出身青樓,卻偏偏與公主長得像背镇,于是被迫代替她去往敵國和親咬展。 傳聞我的和親對象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,901評論 2 345

推薦閱讀更多精彩內(nèi)容

  • 搞懂 Java equals 和 hashCode 方法 分析完 Java List 容器的源碼后瞒斩,本來想直接進(jìn)入...
    醒著的碼者閱讀 1,943評論 1 9
  • Map 我們都知道 Map 是鍵值對關(guān)系的集合破婆,并且鍵唯一,鍵一對一對應(yīng)值胸囱。 關(guān)于 Map 的定義祷舀,大概就這些吧,...
    Anonymous___閱讀 625評論 0 1
  • java.lang.Object類中有兩個(gè)非常重要的方法: 1publicbooleanequals(Object...
    小陳阿飛閱讀 673評論 1 1
  • 親愛的女兒烹笔,我星期五中午就出門裳扯,今晚回到家已經(jīng)十點(diǎn)多了,你早就睡熟了谤职。你把做好的作業(yè)都整齊地放在床邊嚎朽,讓我檢查的。...
    小怪物_a3bf閱讀 146評論 0 4
  • 我柬帕,一名普通大學(xué)生哟忍,半夜十一點(diǎn)開始打現(xiàn)在的內(nèi)容狡门,想說明下自己的感受。 我锅很,怕自己遲早忘了自己的初心其馏。 新的一切又開...
    一饃淺笑安然閱讀 160評論 0 0