第十四章 集合(Set)

一、Set 接口(P518)

1. Set 接口基本介紹

(1)無序(添加和取出的順序不一致),沒有索引。
(2)不允許重復元素,所以最多包含一個 null。
在這里插入圖片描述

2. Set 接口的常用方法

和 List 接口一樣,Set 接口也是 Collection 的子接口,因此,常用方法和 Collection 接口一樣。

3. Set 接口的遍歷方式

同 Collection 的遍歷方式一樣,因為 Set 接口是 Collection 接口的子接口。
(1)可以使用選代器
(2)增強for
(3)不能使用 索引的方式來獲取

二、HashSet(P519)

1. Hashset 的說明

(1)HashSet 實現了 Set 接口。
(2)HashSet 實際上是 HashMap。
(3)可以存放 null 值,但是只能有一個 null。
(4)HashSet 不保證元素是有序的,取決于 hash 后,再確定索引的結果。
(5)不能有重復元素/對象。

2. Hashset底層機制源碼說明(P522)

分析 Hashset 底層是 HashMap,HashMap 底層是(數組+鏈表+紅黑樹)。

public class HashMap_<K, V> {transient Node<K, V>[] table;transient int modCount;transient int size;public V put(K key, V value) {return putVal(hash(key), key, value, false, true);}static final int hash(Object key) {int h;return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);}final V putVal(int hash, K key, V value, boolean onlyIfAbsent,boolean evict) {Node<K, V>[] tab;Node<K, V> p;int n, i;// 屬性table為null或table的長度為0,就擴容if ((tab = table) == null || (n = tab.length) == 0) {n = (tab = resize()).length;}// 如果tab[i]為null,表示沒有存放元素,就創建節點并賦值給tab[i]if ((p = tab[i = (n - 1) & hash]) == null) {tab[i] = newNode(hash, key, value, null);} else {Node<K, V> e;K k;// p 和添加元素的hash值相同 并且 (key相同或equals相同),p賦值給eif (p.hash == hash &&((k = p.key) == key || (key != null && key.equals(k)))) {e = p;}// 鏈表循環比較else {for (int binCount = 0; ; ++binCount) {if ((e = p.next) == null) {p.next = newNode(hash, key, value, null);break;}if (e.hash == hash &&((k = e.key) == key || (key != null && key.equals(k)))) {break;}p = e;}}if (e != null) { // existing mapping for keyV oldValue = e.value;if (!onlyIfAbsent || oldValue == null) {e.value = value;}return oldValue;}}++modCount;if (++size > threshold) {resize();}return null;}int threshold;final float loadFactor = DEFAULT_LOAD_FACTOR;static final int MAXIMUM_CAPACITY = 1 << 30;static final int DEFAULT_INITIAL_CAPACITY = 1 << 4; // 16// 加載因子static final float DEFAULT_LOAD_FACTOR = 0.75f;final Node<K, V>[] resize() {Node<K, V>[] oldTab = table;int oldCap = (oldTab == null) ? 0 : oldTab.length;int oldThr = threshold;int newCap, newThr = 0;if (oldCap > 0) {if (oldCap >= MAXIMUM_CAPACITY) {threshold = Integer.MAX_VALUE;return oldTab;} else if ((newCap = oldCap << 1) < MAXIMUM_CAPACITY &&oldCap >= DEFAULT_INITIAL_CAPACITY) {newThr = oldThr << 1; // double threshold}} else if (oldThr > 0) {newCap = oldThr;} else {// 擴容newCap = DEFAULT_INITIAL_CAPACITY;newThr = (int) (DEFAULT_LOAD_FACTOR * DEFAULT_INITIAL_CAPACITY);}if (newThr == 0) {float ft = (float) newCap * loadFactor;newThr = (newCap < MAXIMUM_CAPACITY && ft < (float) MAXIMUM_CAPACITY ?(int) ft : Integer.MAX_VALUE);}threshold = newThr;// 初始化數組,并賦值給屬性tableNode<K, V>[] newTab = (Node<K, V>[]) new Node[newCap];table = newTab;return newTab;}Node<K, V> newNode(int hash, K key, V value, Node<K, V> next) {return new Node<>(hash, key, value, next);}static class Node<K, V> {final int hash;final K key;V value;Node<K, V> next;Node(int hash, K key, V value, Node<K, V> next) {this.hash = hash;this.key = key;this.value = value;this.next = next;}}
}

(1)HashSet 底層是 HashMap。
(2)添加一個元素時,先得到 hash 值 --> 會轉成 --> 索引值。
(3)找到存儲數據表 table,看這個索引位置是否已經存放的有元素。
(4)如果沒有,直接加入。
(5)如果有,調用 equals 比較,如果相同,就放棄添加,如果不相同,則添加到最后。
(6)在 Java8 中,如果一條鏈表的元素個數達到 TREEIFY_THRESHOLD(默認是8),并且 table 的大小 >= MIN_TREEIFY_CAPACITY(默認64),就會進行樹化(紅黑樹)。

紅黑樹機制:
(1)HashSet 底層是 HashMap,第一次添加時,table 數組擴容到16,臨界值(threshold)是16,加載因子(loadFactor)是0.75=12。
(2)如果table數組使用到了臨界值12,就會擴容到162=32,新的臨界值就是320.75=24,依次類推。
(3)在Java8中,如果一條鏈表的元素個數到達TREEIFY_THRESHOLD(默認是8),并且table的大小>=MIN_TREEIFY_CAPACITY(默認64)就會進行樹化(紅黑樹),否則仍然采用數組擴容機制。

三、LinkedHashSet (P528)

1. LinkedHashSet 的說明

(1)LinkedHashSet 是 Hashset 的子類。
(2)LinkedHashSet 底層是一個 LinkedHashMap,底層維護了一個 數組+雙向鏈表
(3)LinkedHashSet 根據元素的 hashCode 值來決定元素的存儲位置,同時使用鏈表維護元素的 次序(圖),這使得元素看起來是以插入順序保存的。
(4)LinkedHashset 不允許添重復元素。
在這里插入圖片描述
(1)在 LinkedHashSet 中維護了一個 hash 表和雙向鏈表(LinkedHashSet 有 head 和 tail)。
(2)每一個節點有 pre 和 next 屬性,這樣可以形成雙向鏈表。
(3)在添加一個元素時,先求hash值,在求索引,確定該元素在 hashtable 的位置,然后將添加的元素加入到雙向鏈表(如果已經存在,不添加【原則和 hashset 一樣】)。
(4)遍歷 LinkedHashSet 也能確保插入順序和遍歷順序一致。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/536668.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/536668.shtml
英文地址,請注明出處:http://en.pswp.cn/news/536668.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

數據結構:KMP算法

1.何為KMP算法 KMP算法是由Knuth、Morris和Pratt三位學者發明的&#xff0c;所以取了三位學者名字的首字母&#xff0c;叫作KMP算法。 2.KMP的用處 KMP主要用于字符串匹配的問題&#xff0c;主要思想是當出現字符串不匹配時&#xff0c;我們可以知道一部分之前已經匹配過的的文…

【期刊周報1】醫學好刊(SCI/SSCI/EI),含Top,領域廣,接收快!

為了向廣大學者朋友提供更優質的選刊服務&#xff0c;提高選刊質量&#xff0c;我處現開設周報專欄&#xff0c;以羅列我處合作的優質期刊~ 本期&#xff0c;小編給大家推薦的是醫學領域相關的熱門期刊&#xff0c;接收領域廣&#xff0c;無預警&#xff0c;且在最新檢索目錄內…

Python遙感影像深度學習指南(2)-在 PyTorch 中創建自定義數據集和加載器

在上一篇 文章中,我們Fast.ai 在衛星圖像中檢測云輪廓,檢測物體輪廓被稱為語義分割。雖然我們用幾行代碼就能達到 96% 的準確率,但該模型無法考慮數據集中提供的所有輸入通道(紅、綠、藍和近紅外)。問題在于,深度學習框架(如 Keras、Fast.ai 甚至 PyTorch)中的大多數語…

油煙凈化器如何做到高效凈化?科技力量,清新餐飲生活

我最近分析了餐飲市場的油煙凈化器等產品報告&#xff0c;解決了餐飲業廚房油膩的難題&#xff0c;更加方便了在餐飲業和商業場所有需求的小伙伴們。 油煙凈化器的出現&#xff0c;為我們的餐飲生活注入了一抹清新的色彩。然而&#xff0c;它究竟是如何工作的&#xff1f;為何能…

【開題報告】基于SSM的健康飲食系統設計與實現

1.研究背景 如今&#xff0c;隨著人們生活水平的提高和健康意識的增強&#xff0c;越來越多的人開始關注自己的飲食習慣&#xff0c;并希望通過合理的飲食來維持身體健康。然而&#xff0c;對于許多人來說&#xff0c;了解和選擇合適的飲食方式并不容易。傳統的飲食指導往往比…

【并發設計模式】聊聊Immutability模式利用不變性解決并發問題

上一篇文章&#xff0c;我們介紹了如何利用二階段停止協議進行優雅停止線程和線程池&#xff0c;本篇介紹在并發編程中數據安全性&#xff0c;我們知道針對于數據的操作&#xff0c;讀和寫(添加、刪除、修改), 在并發線程讀寫的時候&#xff0c;變量不加鎖的情況下&#xff0c;…

redis哨兵+redis主從復制(在虛擬機centos的docker下)

1.安裝docker Docker安裝(CentOS)簡單使用-CSDN博客 2.redis主從復制 redis主從復制(在虛擬機centos的docker下)-CSDN博客 3.編輯3個redis配置 cd /etc mkdir redis-sentinel cd redis-sentinel/ wget http://download.redis.io/redis-stable/sentinel.confcp sentinel.co…

ssh 免密登陸公鑰設置失敗分析調試

前景 看到這里肯定已經知道如何設置免密登陸。本文主要用于解決免密登陸設置失效問題。 ssh調試 目的 ssh設置了公鑰仍然無法免密登陸; 需要調試 解決 通過systemctl status sshd的日志輸出查看原因 步驟 打開調試 systemctl status sshd查看所在服務文件 $ sudo sys…

【并發編程篇】讀鎖readLock()和寫鎖writeLock()

文章目錄 &#x1f6f8;情景引入?解決問題 readLock()和writeLock()都是ReadWriteLock接口中定義的方法&#xff0c;用于獲取讀鎖和寫鎖。 readLock()方法返回一個讀鎖&#xff0c;允許多個線程同時獲取該鎖&#xff0c;以進行并發讀取操作。如果當前已有一個寫鎖或其他線程正…

GIT具體配置步驟詳解

GIT配置具體步驟如下 SDK 使用 Repo 工具管理&#xff0c;拉取 SDK 需要配置安裝 Repo 工具。 Repo is a tool built on top of Git. Repo helps manage many Git repositories, does the uploads to revision control systems, and automates parts of the development workf…

裝飾器模式和責任鏈模式區別

近期看了 mybatis 的源碼&#xff0c;發現二級緩存這塊用了裝飾器模式將各個功能的緩存進行嵌套&#xff0c;源碼上也是講到使用了裝飾器模式&#xff0c;但是看著跟責任鏈模式類似&#xff0c;本著搞清楚的想法&#xff0c;搜了很多資料&#xff0c;看了書籍《Head First 設計…

AI行業新趨勢:百模大戰中的變革與未來

AI行業新趨勢&#xff1a;百模大戰中的變革與未來 人工智能&#xff0c;這個曾經被視為科幻小說的情節&#xff0c;如今已經成為我們生活中的常態。從智能手機、自動駕駛汽車&#xff0c;到智能家居、醫療診斷&#xff0c;AI的應用已經深入到我們生活的各個角落。然而&#xf…

多維時序 | MATLAB實CNN-BiGRU-Mutilhead-Attention卷積網絡結合雙向門控循環單元網絡融合多頭注意力機制多變量時間序列預測

多維時序 | MATLAB實現CNN-BiGRU-Mutilhead-Attention卷積網絡結合雙向門控循環單元網絡融合多頭注意力機制多變量時間序列預測 目錄 多維時序 | MATLAB實現CNN-BiGRU-Mutilhead-Attention卷積網絡結合雙向門控循環單元網絡融合多頭注意力機制多變量時間序列預測預測效果基本介…

ubuntu 22.04 安裝mysql服務

完整內容&#xff1a; https://developer.aliyun.com/article/1260321 # 安裝服務 sudo apt install mysql-server# 按向導設置root密碼 sudo mysql_secure_installation# 使用設置的密碼登錄 sudo mysql -u root -p也可以使用工具登錄&#xff0c;例如: navicat for mysql

協同工作php,PHPOA:靈活、高效、協同,讓企業高效運轉

原標題&#xff1a;PHPOA&#xff1a;靈活、高效、協同&#xff0c;讓企業高效運轉PHPOA系統作為一個管理系統&#xff0c;它的職責就是為企業高效運轉而服務&#xff0c;以提高企業的辦公效率為己任&#xff0c;減少不必要的資源浪費為責任。它保持高度的靈活性、高效性與協同…

ubuntu搭建php開發環境記錄

2019獨角獸企業重金招聘Python工程師標準>>> 這兩天自己在阿里云上面買了一個ecs&#xff0c;系統選的是ubuntu16.04&#xff0c;第一件事就是先搭環境&#xff0c;這次準備使用lamp組合。 Apache安裝 首先安裝apache服務器&#xff0c;ubuntu下面使用apt-get來下載…

php datediff 函數,dateAdd與DateDiff函數的js代碼

1、DateAdd函數&#xff1a;復制代碼 代碼示例:function DateAdd(interval,number,date){switch(interval.toLowerCase()){case "y": return new Date(date.setFullYear(date.getFullYear()number));case "m": return new Date(date.setMonth(date.getMont…

mysql索引為啥要選擇B+樹 (下)

有讀者在 mysql索引為啥要選擇B樹 (上) 上篇文章中留言總結了選擇 B 樹的原因&#xff0c;大體上說對了&#xff0c;今天我們再一起來看看具體的原因。 索引為什么要保存在硬盤中首先要明白幾個概念&#xff0c;服務器存儲一般分內存和硬盤&#xff0c;內存的大小相對于硬盤來說…

des加解密java c#,C#編寫DES加密、解密類

這個C#類封裝的DES加密解密&#xff0c;可以使用默認秘鑰進行加密、解密&#xff0c;也可以自定義秘鑰進行加密、解密&#xff0c;調用簡單方便。示例一&#xff1a;using System;using System.Security.Cryptography;using System.Text;namespace DotNet.Utilities{/// /// DE…

八年開發程序員淺析SpringBoot 之 Shiro 與 Redis 多級緩存問題

前言 來自不愿意透露姓名的小師弟的投稿。這篇主要講了&#xff0c;項目中配置了多緩存遇到的坑&#xff0c;以及解決辦法。 發現問題 在一次項目實踐中有實現多級緩存其中有已經包括了 Shiro 的 Cache &#xff0c;本以為開啟 redis 的緩存是一件很簡單的事情只需要在啟動類上…