欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Java中的HashSet、LinkedHashSet集合解析

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

Set系列集合

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

Set集合的實(shí)現(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()返回集合中元素的個(gè)數(shù)/集合長度

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

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

1。迭代器

2。增強(qiáng)for

3。Lambda表達(dá)式

public class A01_SetDemo1 {
    public static void main(String[] args) {
        //1.創(chuàng)建一個(gè)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);
        }
        //增強(qiáng)for
        for (String str : s) {
            System.out.println(str);
        }
        //Lambda
        s.forEach(str -> System.out.println(str));
    }
}

HashSet

  • HashSet集合底層采用哈希表存儲(chǔ)數(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)行計(jì)算
  • 一般情況下,會(huì)重寫hashCode方法,利用對象內(nèi)部的屬性值計(jì)算哈希值

對象的哈希值特點(diǎn)

  • 如果沒有重寫hashCode方法,不同對象計(jì)算出的哈希值是不同的
  • 如果已經(jīng)重寫hashCode方法,不同的對象只要屬性值相同,計(jì)算出的哈希值就是一樣的
  • 在小部分情況下,不同的屬性值或者不同地址值計(jì)算出來的哈希值也可能一樣(哈希碰撞)
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方法,不同對象計(jì)算出的哈希值是不同的
        //1554874502
        System.out.println(s1.hashCode());
        //1846274136
        System.out.println(s2.hashCode());
        //重寫hashCode后:不同的對象只要屬性值相同,計(jì)算出的哈希值就是一樣的
        //26209637
        System.out.println(s1.hashCode());
        //26209637
        System.out.println(s2.hashCode());
        //3。在小部分情況下,不同的屬性值或者不同地址值計(jì)算出來的哈希值也可能一樣(哈希碰撞)
        //96354
        System.out.println("abc".hashCode());
        //96354
        System.out.println("acD".hashCode());
    }
}

HashSet的底層原理

在這里插入圖片描述

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

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

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

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

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

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

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

HashSet的三個(gè)問題

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

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

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

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

public class A02_HashSetDemo2 {
    public static void main(String[] args) {
        //1。創(chuàng)建3個(gè)學(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ù)、無索引
  • 這里的有序指的是保證存儲(chǔ)和取出的元素順序一致
  • 原理:底層數(shù)據(jù)結(jié)構(gòu)依然是哈希表,只是每個(gè)元素又額外多了一個(gè)雙鏈表的機(jī)制記錄存儲(chǔ)的順序
public class A04_LinkedHashSetDemo {
    public static void main(String[] args) {
        //1。創(chuàng)建3個(gè)學(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)文章

最新評(píng)論