成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

一個(gè)有趣的問題: 如何用HashSet來存儲(chǔ)重復(fù)的字符串?

AprilJ / 2156人閱讀

摘要:注實(shí)際應(yīng)用中,我們一般是用集合來存儲(chǔ)相同的字符串的,不會(huì)用來存。解答雖然我們不能用來存放類型重復(fù)的字符串,但我們可以用來存儲(chǔ)類型重復(fù)的字符串呀。而對(duì)于類型,相同字符串的不同對(duì)象哈希值是不同的。

有一種學(xué)得快的方法,就是不要一次學(xué)太多。
1. 前言

今天,我們來探討一個(gè)實(shí)際中不常用但卻比較有意思的問題。它能幫助你理解 “HashSet中的鍵值是唯一的,不可重復(fù)的” 這句話的真正含義,也考驗(yàn)?zāi)銓?duì)問題的思考深度。

注:實(shí)際應(yīng)用中,我們一般是用 ArrayList 集合來存儲(chǔ)相同的字符串的,不會(huì)用 HashSet 來存。

我們平時(shí)都看到或聽說 HashSet 是不能用來存放重復(fù)的字符串的,是真的存放不了嗎?如果面試問你這個(gè)問題,你能給出解決方案嗎?

2. 參考解答

先給出參考解答,然后我們?cè)賮矸治鰹槭裁础?

解答:
雖然我們不能用 HashSet 來存放 String 類型重復(fù)的字符串,但我們可以用 HashSet 來存儲(chǔ) StringBuilder 類型重復(fù)的字符串呀。

public class HashSetTest {
    public static void main(String[] args){

        // 用 HashSet 來存放 String 類型的重復(fù)的字符串會(huì)發(fā)生什么?

        HashSet hs1 = new HashSet<>();
        String s1 = new String("aaa");
        String s2 = new String("aaa");
        String s3 = new String("aaa");
        hs1.add(s1);
        hs1.add(s2);
        hs1.add(s3);
        System.out.println("hs1:"+hs1); // 重復(fù)的字符串是存不進(jìn)去的

        // 用 HashSet 來存放 StringBuilder 類型的重復(fù)的字符串又會(huì)發(fā)生什么?

        HashSet hs2 = new HashSet<>();
        StringBuilder sb1 = new StringBuilder("aaa");
        StringBuilder sb2 = new StringBuilder("aaa");
        StringBuilder sb3 = new StringBuilder("aaa");
        hs2.add(sb1);
        hs2.add(sb2);
        hs2.add(sb3);
        System.out.println("hs2:"+hs2); // 咦,結(jié)果發(fā)現(xiàn)重復(fù)的字符串也能存進(jìn)去了


        // 那為什么呢?我們來打印一個(gè)各個(gè)對(duì)象的hashCode看一下

        System.out.println("s1的hashCode:"+s1.hashCode());
        System.out.println("s2的hashCode:"+s2.hashCode());
        System.out.println("s3的hashCode:"+s3.hashCode());
        System.out.println("sb1的hashCode:"+sb1.hashCode());
        System.out.println("sb2的hashCode:"+sb2.hashCode());
        System.out.println("sb3的hashCode:"+sb3.hashCode());

    }
}

輸出結(jié)果:

hs1:[aaa]
hs2:[aaa, aaa, aaa]
s1的hashCode:96321
s2的hashCode:96321
s3的hashCode:96321
sb1的hashCode:356573597
sb2的hashCode:1735600054
sb3的hashCode:21685669

從打印結(jié)果來看,我們是不能用 HashSet 來存放 String 類型的重復(fù)字符串的(如hs1),但我們是可以用HashSet來存放 StringBuilder 類型的重復(fù)字符串。

3. 為什么?

從打印的 hashCode 來看,String 類型,相同字符串的不同 String 對(duì)象哈希值是一樣的。而對(duì)于 StringBuilder 類型,相同字符串的不同對(duì)象哈希值是不同的。

要知道這個(gè)問題的答案,我們首先得了解 Java 虛擬機(jī)是如何判斷兩個(gè)對(duì)象是否相同的。

那 Java 虛擬機(jī)是如何判斷兩個(gè)對(duì)象是否相同的呢?

參考解答:
Java 虛擬機(jī)會(huì)先判斷兩個(gè)對(duì)象的 hashCode 是否相同,如果 hashCode 不同,則說明肯定是兩個(gè)不同的對(duì)象了;如果 hashCode 相同再通過 equals() 方法進(jìn)行進(jìn)一步比較,如果 equals 方法返回 true,則說明兩個(gè)對(duì)象是相同的,如果equals方法返回 false 說明兩個(gè)對(duì)象不同。

具體驗(yàn)證思路如果你感興趣,請(qǐng)查看: JDK 是如何判斷兩個(gè)對(duì)象是否相同的?判斷的流程是什么?

那為什么相同字符串的不同 String 對(duì)象哈希值是一樣的,而且還被虛擬機(jī)判斷為相同的對(duì)象了呢?

因?yàn)?String 類復(fù)寫了 Object 類的 hashCode() 和 equals() 方法,并實(shí)現(xiàn)了自己的 hashCode 值生成算法和 equals 的比較規(guī)則,具有相同字符串內(nèi)容的不同 String 對(duì)象在初始化時(shí)生成的 hashCode 值是一樣的,并且 String 類 equals() 方法比較的是兩個(gè)字符串的內(nèi)容,而不是內(nèi)存地址值,這兩個(gè)條件同時(shí)成立, 這就使 Java 虛擬機(jī)把具有相同內(nèi)容的不同 String 對(duì)象判斷為相同的對(duì)象了,就不會(huì)存入 HashSet 集合中。

而 StringBuilder 為什么就可以呢?它相同內(nèi)容的不同對(duì)象的哈希值值為什么是不同的?

查看 StringBuilder 類的源碼你會(huì)發(fā)現(xiàn),因?yàn)?StringBuilder 并沒有復(fù)寫 Object 類的 hashCode() 方法和 equals() 方法,StringBuilder 用的是父類 Object 類的 hashCode 生成算法,也就是用 native 層的 hashCode 生成算法,很大概率產(chǎn)生的哈希值是不一樣的,即使產(chǎn)生了一樣的哈希值,Object 類的 equals() 方法比較的是兩個(gè)對(duì)象的內(nèi)存地址,而不是兩個(gè)對(duì)象的內(nèi)容,這就使 Java 虛擬機(jī)把具有相同內(nèi)容的 StringBuilder 對(duì)象判斷為不同的對(duì)象,就可以存入 HashSet 集合中了。

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/73408.html

相關(guān)文章

  • Java集合問題大匯總

    摘要:集合中成員很豐富,常用的集合有,,等。實(shí)現(xiàn)接口的集合主要有。集合中不能包含重復(fù)的元素,每個(gè)元素必須是唯一的。而以作為實(shí)現(xiàn)的構(gòu)造函數(shù)的訪問權(quán)限是默認(rèn)訪問權(quán)限,即包內(nèi)訪問權(quán)限。與接口不同,它是由一系列鍵值對(duì)組成的集合,提供了到的映射。 原文地址 Java集合 Java集合框架:是一種工具類,就像是一個(gè)容器可以存儲(chǔ)任意數(shù)量的具有共同屬性的對(duì)象。 Java集合中成員很豐富,常用的集合有Arra...

    894974231 評(píng)論0 收藏0
  • Java集合框架——Set接口

    摘要:如果你知道用集合,就用。在集合中常見的數(shù)據(jù)結(jié)構(gòu)底層數(shù)據(jù)結(jié)構(gòu)是數(shù)組,查詢快,增刪慢底層數(shù)據(jù)結(jié)構(gòu)是鏈表,查詢慢,增刪快底層數(shù)據(jù)結(jié)構(gòu)是哈希表。依賴兩個(gè)方法和底層數(shù)據(jù)結(jié)構(gòu)是二叉樹。 第三階段 JAVA常見對(duì)象的學(xué)習(xí) 集合框架——Set接口 showImg(https://segmentfault.com/img/remote/1460000019683927?w=700&h=280); Lis...

    Ashin 評(píng)論0 收藏0
  • Java編程基礎(chǔ)18——集合(Set集合)

    摘要:并把最終的隨機(jī)數(shù)輸出到控制臺(tái)。方法,在集合中如何存儲(chǔ)元素取決于方法的返回值返回,集合中只有一個(gè)元素。創(chuàng)建集合對(duì)象,傳入比較器。 1_HashSet存儲(chǔ)字符串并遍歷 A:Set集合概述及特點(diǎn) 通過API查看即可 B:案例演示 HashSet存儲(chǔ)字符串并遍歷 import java.util.HashSet; public class Demo1_HashSet { p...

    SexySix 評(píng)論0 收藏0
  • 1、List接口 2、Set接口 3、判斷集合唯一性原理

    摘要:接口的特點(diǎn)接口的特點(diǎn)它是一個(gè)元素存取有序的集合。導(dǎo)致迭代器并不知道集合中的變化,容易引發(fā)數(shù)據(jù)的不確定性。枚舉已被迭代器替代。集合取出元素的方式可以采用迭代器增強(qiáng)。 01List接口的特點(diǎn) A:List接口的特點(diǎn): ?a:它是一個(gè)元素存取有序的集合。 例如,存元素的順序是11、22、33。那么集合中,元素的存儲(chǔ)就是按照11、22、33的順序完成的)。 ?b:它是一個(gè)帶有索引的...

    gnehc 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

閱讀需要支付1元查看
<