亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

Java中的HashSet、LinkedHashSet集合解析

 更新時間:2023年11月01日 09:31:01   作者:追光而遇  
這篇文章主要介紹了Java中的HashSet、LinkedHashSet集合解析,與HashSet不同的是,LinkedHashSet在內(nèi)部使用了一個雙向鏈表來維護元素的順序,因此它可以保持元素的插入順序,這使得LinkedHashSet在需要保持元素順序的場景下非常有用,需要的朋友可以參考下

Set系列集合

  • List系列集合:添加的元素是有序、可重復(fù)、有索引
  • Set系列集合:添加的元素是無序、不可重復(fù)、無索引
    • 無序:存取順序不一致
    • 不重復(fù):可以去除重復(fù)
    • 無索引:沒有帶索引的方法,所以不能使用普通for循環(huán)遍歷,也不能通過索引來獲取元素

Set集合的實現(xiàn)類

  • HashSet:無序、不重復(fù)、無索引
    • LinkedHashSet:有序、不重復(fù)、無索引
  • TreeSet:可排序、不重復(fù)、無索引

Set接口中的方法上基本上與Collection的API一致  

Collection

Collection是單列集合的祖宗接口,它的功能是全部單列集合都可以繼承使用的

方法名稱說明
public boolean add(E e)把給定的對象添加到當(dāng)前集合中
public void clear()清空集合中所有的元素
public boolean remove(E e)把給定的對象在當(dāng)前集合中刪除
public boolean contains(Object obj)判斷當(dāng)前集合中是否包含給定的對象
public boolean isEmpty()判斷當(dāng)前集合是否為空
public int size()返回集合中元素的個數(shù)/集合長度

練習(xí):存儲字符串并遍歷

利用Set系列的集合,添加字符串,并使用多種方式遍歷

1。迭代器

2。增強for

3。Lambda表達(dá)式

public class A01_SetDemo1 {
    public static void main(String[] args) {
        //1.創(chuàng)建一個Set集合的對象
        Set<String> s = new HashSet<>();
        //2.添加元素
        boolean r1 = s.add("朵朵");
        boolean r2 = s.add("朵朵");
        //true
        System.out.println(r1);
        //false
        System.out.println(r2);
        //[朵朵]
        System.out.println(s);
        boolean r3 = s.add("小七");
        boolean r4 = s.add("鋼镚");
        //無序
        //[鋼镚, 朵朵, 小七]
        System.out.println(s);
        //迭代器遍歷
        Iterator<String> it = s.iterator();
        while (it.hasNext()) {
            String str = it.next();
            System.out.println(str);
        }
        //增強for
        for (String str : s) {
            System.out.println(str);
        }
        //Lambda
        s.forEach(str -> System.out.println(str));
    }
}

HashSet

  • HashSet集合底層采用哈希表存儲數(shù)據(jù)
  • 哈希表是一種對與增刪改查數(shù)據(jù)性能都較好的結(jié)構(gòu)

哈希表組成

  • JDK8之前:數(shù)組+鏈表
  • JDK8之后:數(shù)組+鏈表+紅黑樹

哈希值

對象的整數(shù)表現(xiàn)形式

  • 根據(jù)hashCode方法算出來的int類型的整數(shù)
  • 該方法定義在Object類中,所有對象都可以調(diào)用,默認(rèn)使用地址值進(jìn)行計算
  • 一般情況下,會重寫hashCode方法,利用對象內(nèi)部的屬性值計算哈希值

對象的哈希值特點

  • 如果沒有重寫hashCode方法,不同對象計算出的哈希值是不同的
  • 如果已經(jīng)重寫hashCode方法,不同的對象只要屬性值相同,計算出的哈希值就是一樣的
  • 在小部分情況下,不同的屬性值或者不同地址值計算出來的哈希值也可能一樣(哈希碰撞)
public class A02_HashSetDemo1 {
    public static void main(String[] args) {
        //1。創(chuàng)建對象
        Student s1 = new Student("朵朵", 5);
        Student s2 = new Student("朵朵", 5);
        //2。 如果沒有重寫hashCode方法,不同對象計算出的哈希值是不同的
        //1554874502
        System.out.println(s1.hashCode());
        //1846274136
        System.out.println(s2.hashCode());
        //重寫hashCode后:不同的對象只要屬性值相同,計算出的哈希值就是一樣的
        //26209637
        System.out.println(s1.hashCode());
        //26209637
        System.out.println(s2.hashCode());
        //3。在小部分情況下,不同的屬性值或者不同地址值計算出來的哈希值也可能一樣(哈希碰撞)
        //96354
        System.out.println("abc".hashCode());
        //96354
        System.out.println("acD".hashCode());
    }
}

HashSet的底層原理

在這里插入圖片描述

1.創(chuàng)建一個默認(rèn)長度16,默認(rèn)加載因子0.75的數(shù)組,數(shù)組名table

  • 加載因子:擴容時機
  • 當(dāng)存入數(shù)據(jù)達(dá)到16 x 0.75 = 12時候,數(shù)組擴容成原數(shù)組的二倍
  • JKD8以后:當(dāng)鏈表長度大于8而且數(shù)組長度大于等于64,當(dāng)前鏈表自動轉(zhuǎn)成紅黑樹,增加查找效率

2.根據(jù)元素的哈希值跟數(shù)組的長度計算出應(yīng)存入的位置

  • int index = (數(shù)組長度 - 1) & 哈希值;
  • 如果集合中存儲的是自定義對象,必須要重寫hashCode和equsl方法

3.判斷當(dāng)前位置是否為null,如果是null直接存入(添加元素)

4.如果位置不是null,表示有元素,則調(diào)用equals方法比較屬性值

  • 一樣:不存 ------ 不一樣:存入數(shù)組,形成鏈表
  • JDK8以前:新元素存入數(shù)組,老元素掛在新元素下面
  • JDK8以后:新元素掛在老元素下面

HashSet的三個問題

  • 問題1.HashSet為什么存和取的順序不一樣?
    • HashSet遍歷是從數(shù)組的0索引開始,一條鏈表一條鏈表(或紅黑樹)的遍歷,可能和存儲時候的順序不一樣
  • 問題2.HashSet為什么沒有索引?
    • HashSet不夠純粹,在底層是鏈表 數(shù)組 紅黑樹三種組合,定義誰都不合適。
    • 假設(shè)使用數(shù)組的索引,但一個索引處可能會有鏈表,不可能鏈表上所有的數(shù)據(jù)都是一個索引
  • 問題3.HashSet是利用什么機制保證數(shù)據(jù)去重復(fù)的
    • HashCode方法 --> 哈希值 --> 確定元素添加在哪個位置
    • equals方法 --> 比較內(nèi)部的屬性值是否相同(自定義對象要重寫這兩種方法)

練習(xí):利用HashSet集合去除重復(fù)元素

需求:創(chuàng)建一個存儲學(xué)生對象的集合,存儲多個學(xué)生對象 使用程序?qū)崿F(xiàn)在控制臺遍歷該集合

要求:學(xué)生對象的成員變量值相同,我們就認(rèn)為是同一個對象

public class A02_HashSetDemo2 {
    public static void main(String[] args) {
        //1。創(chuàng)建3個學(xué)生對象
        Student s1 = new Student("朵朵", 5);
        Student s2 = new Student("小七", 7);
        Student s3 = new Student("鋼镚", 9);
        Student s4 = new Student("朵朵", 5);
        //2。創(chuàng)建集合用來添加學(xué)生
        HashSet<Student> hs = new HashSet<>();
        //3。添加元素(重寫hashCode和equal方法后)
        //true
        System.out.println(hs.add(s1));
        //true
        System.out.println(hs.add(s2));
        //true
        System.out.println(hs.add(s3));
        //false
        System.out.println(hs.add(s4));
        //4。打印集合
        //[Student{name = 小七, age = 7}, Student{name = 鋼镚, age = 9}, Student{name = 朵朵, age = 5}]
        System.out.println(hs);
    }
}

LinkedHashSet

LinkedHashSet底層原理

  • 有序、不重復(fù)、無索引
  • 這里的有序指的是保證存儲和取出的元素順序一致
  • 原理:底層數(shù)據(jù)結(jié)構(gòu)依然是哈希表,只是每個元素又額外多了一個雙鏈表的機制記錄存儲的順序
public class A04_LinkedHashSetDemo {
    public static void main(String[] args) {
        //1。創(chuàng)建3個學(xué)生對象
        Student s1 = new Student("朵朵", 5);
        Student s2 = new Student("小七", 7);
        Student s3 = new Student("鋼镚", 9);
        Student s4 = new Student("朵朵", 5);

        //2。創(chuàng)建集合用來添加學(xué)生
        LinkedHashSet<Student> lhs = new LinkedHashSet<>();

        //3。添加元素(重寫hashCode和equal方法后)
        //true
        System.out.println(lhs.add(s1));
        //true
        System.out.println(lhs.add(s2));
        //true
        System.out.println(lhs.add(s3));
        //false
        System.out.println(lhs.add(s4));

        //4。打印集合
        //與添加順序一樣
        //[Student{name = 朵朵, age = 5}, Student{name = 小七, age = 7}, Student{name = 鋼镚, age = 9}]
        System.out.println(lhs);
    }
}

數(shù)據(jù)去重

  • 默認(rèn)使用HashSet
  • 如果要求去重且存取有序,才使用LinkedHashSet

到此這篇關(guān)于Java中的HashSet、LinkedHashSet集合解析的文章就介紹到這了,更多相關(guān)Java中的HashSet、LinkedHashSet內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • springboot 接口返回字符串帶引號的問題解決

    springboot 接口返回字符串帶引號的問題解決

    本文主要介紹了springboot 接口返回字符串帶引號的問題解決,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2022-04-04
  • Spring學(xué)習(xí)之開發(fā)環(huán)境搭建的詳細(xì)步驟

    Spring學(xué)習(xí)之開發(fā)環(huán)境搭建的詳細(xì)步驟

    本篇文章主要介紹了Spring學(xué)習(xí)之開發(fā)環(huán)境搭建的詳細(xì)步驟,具有一定的參考價值,有興趣的可以了解一下
    2017-07-07
  • 淺談Java的String中的subString()方法

    淺談Java的String中的subString()方法

    下面小編就為大家?guī)硪黄獪\談Java的String中的subString()方法。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2016-10-10
  • 在Java編程中使用正則表達(dá)式

    在Java編程中使用正則表達(dá)式

    這篇文章主要介紹了在Java編程中使用正則表達(dá)式,注意使用matches()方法檢測一下Java對正則表達(dá)式的支持情況,需要的朋友可以參考下
    2015-08-08
  • Java調(diào)用WebService接口的方法

    Java調(diào)用WebService接口的方法

    這篇文章主要介紹了Java調(diào)用WebService接口的方法,實例分析了有參方法Add的使用技巧,需要的朋友可以參考下
    2015-01-01
  • Java?IO流之StringWriter和StringReader用法分析

    Java?IO流之StringWriter和StringReader用法分析

    這篇文章主要介紹了Java?IO流之StringWriter和StringReader用法分析,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2021-12-12
  • Java創(chuàng)建線程池的幾種方式代碼示例

    Java創(chuàng)建線程池的幾種方式代碼示例

    這篇文章主要介紹了Java中創(chuàng)建線程池的四種方式,包括使用Executors類、ThreadPoolExecutor類、Future和Callable接口以及Spring的ThreadPoolTaskExecutor,文中通過代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2025-01-01
  • SpringBoot項目yml配置文件不自動提示解決方案

    SpringBoot項目yml配置文件不自動提示解決方案

    這篇文章主要介紹了SpringBoot項目配置文件.yaml/.yml文件編寫時沒有自動提示的解決方案,文章通過圖文結(jié)合的方式給大家講解的非常詳細(xì),需要的朋友可以參考下
    2024-06-06
  • Java讀取OpenSSL生成的PEM公鑰文件操作

    Java讀取OpenSSL生成的PEM公鑰文件操作

    這篇文章主要介紹了Java讀取OpenSSL生成的PEM公鑰文件操作,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2020-10-10
  • Java中使用Hutool的DsFactory操作多數(shù)據(jù)源的實現(xiàn)

    Java中使用Hutool的DsFactory操作多數(shù)據(jù)源的實現(xiàn)

    在Java開發(fā)中,管理多個數(shù)據(jù)源是一項常見需求,Hutool作為一個全能的Java工具類庫,提供了DsFactory工具,幫助開發(fā)者便捷地操作多數(shù)據(jù)源,感興趣的可以了解一下
    2024-09-09

最新評論