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

Java Set接口及常用實(shí)現(xiàn)類總結(jié)

 更新時(shí)間:2023年01月06日 11:33:23   作者:館主阿牛  
Collection的另一個(gè)子接口就是Set,他并沒(méi)有我們List常用,并且自身也沒(méi)有一些額外的方法,全是繼承自Collection中的,因此我們還是簡(jiǎn)單總結(jié)一下,包括他的常用實(shí)現(xiàn)類HashSet、LinkedHashSet、TreeSet的總結(jié)

前言

Collection的另一個(gè)子接口就是Set,他并沒(méi)有我們List常用,并且自身也沒(méi)有一些額外的方法,全是繼承自Collection中的,因此我們還是簡(jiǎn)單總結(jié)一下,包括他的常用實(shí)現(xiàn)類HashSet、LinkedHashSet、TreeSet的總結(jié)!

概述

  • Set 接口是 Collection 的子接口, set 接口沒(méi)有提供額外的方法。
  • Set 集合不允許包含相同的元素,如果試把兩個(gè)相同的元素加入同一個(gè)
    Set 集合中,則添加操作失敗。
  • Set 判斷兩個(gè)對(duì)象是否相同不是使用 == 運(yùn)算符,而是根據(jù)equals()方法。

Set 無(wú)序性與不可重復(fù)性的理解

無(wú)序性

不等于隨機(jī)性。

public static void main(String[] args) {
        Set set = new HashSet();
        set.add("aniu");
        set.add(666);
        set.add("yyds");
        Iterator iterator = set.iterator();
        while(iterator.hasNext()){
            System.out.println(iterator.next());
        }
    }

可以看到,他遍歷輸出的結(jié)果不同于元素添加順序。但千萬(wàn)不要認(rèn)為這就是無(wú)序性,這一點(diǎn)你可以對(duì)比LinkedHashSet,他也是無(wú)序的,但他區(qū)別于HashSet,他可以按照添加順訊遍歷Set。因此,這里無(wú)序性要從底層存儲(chǔ)數(shù)據(jù)的角度理解:Set存儲(chǔ)的數(shù)據(jù)在底層數(shù)組中并非按照數(shù)組索引的順序添加,而是根據(jù)數(shù)據(jù)的哈希值。

不可重復(fù)性

保證添加的元素按照equals()判斷時(shí),不能返回True,即相同的元素只能添加一個(gè)。

需要注意的是,對(duì)于自定義類實(shí)現(xiàn)的對(duì)象,一定要重寫(xiě)hashcode和equals方法才能保證判斷他們是否相等。

可以看下面這段代碼:

import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;

/**
 * @Author:Aniu
 * @Date:2023/1/5 17:24
 * @description TODO
 */
public class Demo {
    public static void main(String[] args) {
        Set set = new HashSet();
        set.add("aniu");
        set.add(666);
        set.add("yyds");
        set.add(new Stu("aniu",21));
        set.add(new Stu("aniu",21));
        Iterator iterator = set.iterator();
        while(iterator.hasNext()){
            System.out.println(iterator.next());
        }
    }
}

class Stu{
    String name;
    int age;

    public Stu(String name, int age) {
        this.name = name;
        this.age = age;
    }

    @Override
    public String toString() {
        return "Stu{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (!(o instanceof Stu)) return false;

        Stu stu = (Stu) o;

        if (age != stu.age) return false;
        return name != null ? name.equals(stu.name) : stu.name == null;
    }
    
}

可以發(fā)現(xiàn)我們之只重寫(xiě)equals是不行的!

重寫(xiě)hashcode后再看結(jié)果:

@Override
    public int hashCode() {
        int result = name != null ? name.hashCode() : 0;
        result = 31 * result + age;
        return result;
    }

可以看到成功去掉了自定義對(duì)象的重復(fù)。這個(gè)和Set的底層存儲(chǔ)原理有關(guān),我們下面會(huì)寫(xiě)到!

Set 接口常用實(shí)現(xiàn)類

HashSet

作為Set接口的主要實(shí)現(xiàn)類,他是線程不安全的,可以存儲(chǔ)null值!

HashSet中元素的添加過(guò)程

我們以HashSet為例,來(lái)大概說(shuō)一下Set元素的添加過(guò)程:

我們向 Hashset 中添加元素 a ,首先調(diào)用元素 a 所在類的 hashcode ()方法,計(jì)算元素 a 的哈希值,此哈希值接著通過(guò)某種算法計(jì)算出 HashSet 底層數(shù)組中的存放位置(即為:索引位置),判斷數(shù)組此位置上是否已經(jīng)有元素:

1.如果此位置上沒(méi)有其他元素,則元素 a 添加成功。

2.如果此位置上有其他元素(或以鏈表形式存在的多個(gè)元素),則比較元素a與元素 b 的 hash 值:

a.如果 hash 值不相同,則元素 a 添加成功。

b.如果 hash 值相同,進(jìn)而需要調(diào)用元素 a 所在類的 equals ()方法:

  • equals ()返回 true ,元素 a 添加失敗
  • equaLs ()返回 false ,則元素 a 添加成功。

對(duì)于添加成功的而言,如果通過(guò)hash值計(jì)算出的數(shù)組索引相同,則元素 a 與已經(jīng)存在指定索引位置上數(shù)據(jù)以鏈表的方式存儲(chǔ)。

這也就是上面不可重復(fù)性里寫(xiě)到的,對(duì)于自定義類實(shí)現(xiàn)的對(duì)象,一定要重寫(xiě)hashcode和equals方法才能保證判斷他們是否相等。

這里源碼就不分析了,因?yàn)?HashSet的底層是HashMap,我們后面會(huì)總結(jié)HashMap的源碼分析!

LinkedHashSet

是HashSet的子類,遍歷其內(nèi)部數(shù)據(jù)時(shí),可以按照添加的順序遍歷!

public static void main(String[] args) {
        Set set = new LinkedHashSet();
        set.add("aniu");
        set.add(666);
        set.add("yyds");
        Iterator iterator = set.iterator();
        while(iterator.hasNext()){
            System.out.println(iterator.next());
        }
    }

LinkedHashSet為什么可以按照添加的元素順序來(lái)遍歷呢,看下面這張圖就行了:

LinkedHashSet在原有HashSet的基礎(chǔ)上提供了雙向鏈表,保證了便歷時(shí)的順序輸出!

對(duì)于頻繁的便利操作,LinkedHashSet的效率高于HashSet!

TreeSet

可以按照添加的元素的指定屬性進(jìn)行排序,因此,他要求添加的元素是同一數(shù)據(jù)類型!

public class Demo {
    public static void main(String[] args) {
        Set set = new TreeSet();
        set.add(3);
        set.add(21);
        set.add(15);
        set.add(6);
        Iterator iterator = set.iterator();
        while(iterator.hasNext()){
            System.out.println(iterator.next());
        }
    }
}

對(duì)于自定義類的對(duì)象,就需要我們前面總結(jié)的自然排序和定制排序了,這里不再寫(xiě)案例!

那再看看TreeSet的存儲(chǔ)結(jié)構(gòu):

以上就是Java Set接口及常用實(shí)現(xiàn)類總結(jié)的詳細(xì)內(nèi)容,更多關(guān)于Java Set接口的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • 關(guān)于Spring?Data?Jpa?自定義方法實(shí)現(xiàn)問(wèn)題

    關(guān)于Spring?Data?Jpa?自定義方法實(shí)現(xiàn)問(wèn)題

    這篇文章主要介紹了關(guān)于Spring?Data?Jpa?自定義方法實(shí)現(xiàn)問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-12-12
  • Java匿名內(nèi)部類和Lambda(->) 的多種寫(xiě)法總結(jié)

    Java匿名內(nèi)部類和Lambda(->) 的多種寫(xiě)法總結(jié)

    這篇文章主要和大家分享一下Java匿名內(nèi)部類和Lambda(->) 的多種寫(xiě)法,文中的示例代碼講解詳細(xì),對(duì)我們學(xué)習(xí)Java有一定幫助,需要的可以先看一下
    2022-07-07
  • 使用java實(shí)現(xiàn)http多線程斷點(diǎn)下載文件(二)

    使用java實(shí)現(xiàn)http多線程斷點(diǎn)下載文件(二)

    下載工具我想沒(méi)有幾個(gè)人不會(huì)用的吧,前段時(shí)間比較無(wú)聊,花了點(diǎn)時(shí)間用java寫(xiě)了個(gè)簡(jiǎn)單的http多線程下載程序,我實(shí)現(xiàn)的這個(gè)http下載工具功能很簡(jiǎn)單,就是一個(gè)多線程以及一個(gè)斷點(diǎn)恢復(fù),當(dāng)然下載是必不可少的,需要的朋友可以參考下
    2012-12-12
  • springboot+mybatis配置控制臺(tái)打印sql日志的方法

    springboot+mybatis配置控制臺(tái)打印sql日志的方法

    這篇文章主要介紹了springboot+mybatis配置控制臺(tái)打印sql日志的方法,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2020-08-08
  • spring?boot?導(dǎo)出數(shù)據(jù)到excel的操作步驟(demo)

    spring?boot?導(dǎo)出數(shù)據(jù)到excel的操作步驟(demo)

    這篇文章主要介紹了spring?boot?導(dǎo)出數(shù)據(jù)到excel的實(shí)現(xiàn)步驟,文中通過(guò)打開(kāi)一個(gè)平時(shí)練習(xí)使用的springboot的demo給大家詳細(xì)介紹,需要的朋友可以參考下
    2022-03-03
  • Java實(shí)現(xiàn)在正則表達(dá)式中控制大小寫(xiě)的方法

    Java實(shí)現(xiàn)在正則表達(dá)式中控制大小寫(xiě)的方法

    這篇文章主要介紹了Java實(shí)現(xiàn)在正則表達(dá)式中控制大小寫(xiě)的方法,結(jié)合實(shí)例形式分析了java正則表達(dá)式中傳遞控制參數(shù)的功能與相關(guān)操作技巧,需要的朋友可以參考下
    2017-04-04
  • JDK源碼白話解讀之ThreadLocal篇

    JDK源碼白話解讀之ThreadLocal篇

    其實(shí)網(wǎng)上有很多關(guān)于ThreadLocal的文章了,有不少文章也已經(jīng)寫(xiě)的非常好了。但是很多同學(xué)反應(yīng)還有一些部分沒(méi)有講解的十分清楚,還是有一定的疑惑沒(méi)有想的十分清楚
    2022-02-02
  • 詳解jvm中的標(biāo)量替換

    詳解jvm中的標(biāo)量替換

    這篇文章主要介紹了詳解jvm中的標(biāo)量替換,幫助大家更好的理解和使用Java虛擬機(jī),感興趣的朋友可以了解下
    2020-09-09
  • 一篇文章帶你入門(mén)Java方法詳解

    一篇文章帶你入門(mén)Java方法詳解

    這篇文章主要介紹了簡(jiǎn)單了解Java方法的定義和使用實(shí)現(xiàn)詳解,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2021-08-08
  • java正則表達(dá)式簡(jiǎn)單應(yīng)用

    java正則表達(dá)式簡(jiǎn)單應(yīng)用

    這篇文章主要介紹了java正則表達(dá)式簡(jiǎn)單應(yīng)用,在之前幾篇文章中已經(jīng)深入學(xué)習(xí)了java正則表達(dá)式基礎(chǔ)知識(shí),本文對(duì)java正則表達(dá)式應(yīng)用進(jìn)行研究,感興趣的小伙伴們可以參考一下
    2015-12-12

最新評(píng)論