Collection單列集合總結

来源:https://www.cnblogs.com/wanghycoder/archive/2023/03/19/17231876.html
-Advertisement-
Play Games

這篇文章記錄了Collection集合,List集合,Set集合 在文章第七點總結了兩大系列集合的五種實現類的區別,有需要的小伙伴可以直接去查看 一、什麼是集合 集合是Java中存儲對象數據的一種容器 二、集合有什麼特點 大小不固定,類型也可以不固定(通常需要泛型約束) 集合只能存儲引用數據類型 集 ...


這篇文章記錄了Collection集合,List集合,Set集合

在文章第七點總結了兩大系列集合的五種實現類的區別,有需要的小伙伴可以直接去查看

一、什麼是集合

集合是Java中存儲對象數據的一種容器

二、集合有什麼特點

  1. 大小不固定,類型也可以不固定(通常需要泛型約束)
  2. 集合只能存儲引用數據類型
  3. 集合適合對容器中的元素進行增刪操作

三、體繫結構

Collection單列集合,每個元素(數據)只包含一個值。

Map雙列集合,每個元素包含兩個值(鍵值對)。

四、Collection

1. 什麼是Collection

官方的解釋

  • Collection是集合層次結構中的根介面。 集合表示一組對象,稱為其元素 。 有些集合允許重覆元素而其他集合則不允許。 有些是有序的,有些是無序的。
  • JDK不提供此介面(Collection)的任何直接實現:它提供了更具體的子介面的實現,如 Set 和 List
  • 此介面通常用於傳遞集合併在需要最大通用性的情況下對其進行操作。

說的通俗一點就是

  • Collection是根介面,所有集合都來自Collection
  • jdk不提供該介面實現類對象,但提供了更具體的實現類
  • 就好比父類和子類,你可以用父類對象接收一個子類的實例化對象

   例如:Father f = new Sun(); // Sun類繼承了Father類

2. Collection的體繫結構

3. 常用方法

方法名稱

說明

public boolean add(E e)

把給定的對象添加到當前集合中

public void clear()

清空集合中所有的元素

public boolean remove(Object o)

把給定的對象在當前集合中出現的第一個位置刪除,如果刪除失敗返回false

public boolean contains(Object obj)

判斷當前集合中是否包含給定的對象

public boolean isEmpty()

判斷當前集合是否為空

public int size()

返回集合中元素的個數。

public Object[] toArray()

把集合中的元素,存儲到數組中

4. 集合的遍歷方式

4.1 迭代器

Iterator是集合專用的迭代方法,只能集合調用

Iterator中常用方法

  • next():返回迭代中的下一個元素
  • hasNext():如果迭代具有更多元素,則返回true
Collection<Integer> list = new ArrayList<>();
Iterator<Integer> iterator = list.iterator();
while(iterator.hasNext()){
    Integer next = iterator.next();
    System.out.println(next);
}

註意事項

  1. 迭代器只能使用一次
  2. next()移動指針到下一個元素,如果沒有拋異常
  3. hasNext()檢查下一個元素是否為空,但不移動指針
  4. 迭代器迭代元素越界出現:NoSuchElementException

4.2 普通for

只適用於List系列集合,因為他有序

通過調用集合的get方法,根據索引取值

4.3 增強for

List<Integer> list = new ArrayList<>();
list.add(1);
list.add(3);
list.add(2);
//增強for
for (int i : list) {
    if (i == 3) {
        i = 5;//增強for中如果對取出的這個元素修改,將不會對集合產生影響
    }
    System.out.println(i);
}

4.4 Lambda迭代

// 使用lambda表達式集合的迭代 
colStr.forEach(new Consumer() { 
    @Override public void accept(String s) { 
        System.out.println(s); 
    } 
}); 
// 簡化寫法 
System.out.println("-------------------------"); 
colStr.forEach(s-> System.out.println(s)); 
System.out.println("-------------------------"); 
// 再次簡化 
colStr.forEach(System.out::println);

五、List

Collection的子介面

1. 特點

有序,有索引(是獨有的),可重覆,可存儲null值,此實現不同步,線程不安全

存儲和取出順序一致

2. 特有方法

方法名稱

說明

註意

void add(int index, E element)

將給定的元素插入到指定位置

索引不能越界,否則報錯

 

E get(int index)

返回該索引位置的元素,沒找到返回-1

E set(int index, E element)

對給定位置的元素進行替換

E remove(int index)

刪除指定位置的元素

int lastIndexOf(Object o)

返回特定元素在集合中最後一次出現的位置

沒找到返回-1

int indexOf(Object o)

返回特定元素在集合中第一次出現的位置

ListIterator<E> listIterator()

List集合特有的迭代器

 

List<E> subList(int fromIndex, int toIndex)

根據開始索引和結束索引(左閉右開)返回一個新的集合,該集合是原集合的子集

 

ListIterator叫做列表迭代器,將在第3.2解釋

3. 迭代方式

和Collection一樣的:迭代器、增強for、Lambda表達式

List獨有的:listIterator、普通for(因為有索引)

3.1 併發修改異常

迭代器在迭代集合,但是集合本身被修改,換而言之:就是在同一時刻只能有一個對象來操作集合,否則就會出現併發修改異常

下麵兩種情況會出現併發修改異常

  1. 迭代器和集合方法都會對集合進行操作

List<String> list = new ArrayList<>();
list.add("java");
list.add("css");
list.add("python");

while(stringListIterator.hasNext()){ 
    String ele = stringListIterator.next(); 
    if("css".equals(ele)){ 
        stringListIterator.remove();//允許 
        //list.remove("css");// 不允許 出現 ConcurrentModificationException 
    } 
    System.out.println(ele); 
}

  2. 增強for本身也是一個Iterator迭代器,同樣不能使用

List<String> list = new ArrayList<>();
list.add("java");
list.add("css");
list.add("python");

for (String s : list) {
    if("css".equals(s)){
        list.remove("css");//不允許,併發修改異常
    }
    System.out.println(s);
}

不會出現併發修改異常

List<String> list = new ArrayList<>();
list.add("java");
list.add("css");
list.add("python");

for (int i= 0; i < list.size();i++){ 
    String ele = list.get(i); 
    if("css".equals(ele)){ 
        list.remove("css");// 允許 
    } 
} 
System.out.println(list);

併發修改異常總結

  1. 同一時間只能有一個對象操作集合
  2. 使用迭代器要保證集合不在改變
  3. 出現異常的原因:
    1. 迭代器在進行遍歷過程中,如果對數組進行操作,會導致迭代器的實際修改值和集合的預期修改值不對應,就會出異常
    2. 迭代器是一次性的,如果對集合進行操作,沒有及時更新迭代器就會引發異常
  4. 如何解決併發修改異常
    1. 使用普通for:用索引取值,同一時間只有一個對象對集合操作
    2. 使用列表迭代器ListIterator

3.2 ListIterator

  • ListIterator的兩個遍歷方法

boolean hasNext()

從前往後遍歷

boolean hasPrevious()

從後往前遍歷,前提是先得從前往後遍歷一遍,讓迭代器指針走到末尾

List<String> list = new ArrayList<>();
ListIterator<String> listIterator = list.listIterator();
  • ListIterator和Iterator的區別
    1. ListIterator每進行一次迭代都會把實際修改值重新賦值給預期修改值,但是Iterator不行
    2. ListIterator是List集合特有的,Iterator是所有集合都有的

4. 兩個主要的介面實現類

4.1 特點

List的介面實現類,List的特點就是ArrayList、LinkedList的特點

4.2 ArrayList

  • 使用的是數組,預設容量為10
  • 一旦數組滿了,則創建一個新的數組,新數組的容量是原數組的容量的1.5倍。並且會將原數組內容複製到新數組
  • 因為底層是數組,具有數組的特點:查詢快,增刪慢

  • 可存儲null值
  • 此實現不同步,線程不安全

4.3 LinkedList

  • 底層是雙向鏈表
  • 具有鏈表的特點:查詢慢,增刪快
  • 此實現不同步,線程不安全
  • 常用方法

六、Set

1. 特點

元素唯一,無序,沒有索引,最多只能一個null

三個主要的介面實現類

HashSet、TreeSet、LinkedHashSet

2. HashSet

2.1 特點:無序(HashSet只是不保證有序,並不是保證無序),不重覆,無索引,此實現不同步

2.2 底層實現:哈希表,是一種對增刪改查性能都較好的結構

  • 哈希表組成

  jdk8之前:數組+鏈表

  jdk8之後:數組+鏈表+紅黑樹

  • 哈希值

  • 哈希值是jdk根據對象計算得出的記憶體地址,根據某個規則算出來的int類型數值
  • 對象可以通過調用hashCode()返回對象的哈希值
  • 同一個對象的哈希值是相同的
  • 在預設情況下,不同對象的哈希值是相同的(除非重寫了hashCode方法

2.3 HashSet底層存儲結構

  1. 當調用無參hashSet構造器,會預設創建一個長度為16的數組
  2. 添加元素,元素哈希值數組長度根據哈希演算法計算元素存儲位置
  3. 判斷該位置是否為空,如果為空直接存數組
  4. 如果位置不為空,判斷哈希值,如果不同直接存鏈表
  5. 如果哈希值相同,判斷equals是否相同,如果不同直接存鏈表
  6. 如果都相同就不存
  • 版本差異

  jdk8之前:新元素占據舊元素位置,指向舊元素。當元素鏈表掛載元素過多會造成查詢性能下降。

  jdk8之後:新元素掛在舊元素下麵。當鏈表長度超過8時,自動將鏈表轉換為紅黑樹,進一步提高性能

  • 元素去重原理(面試會問

  1. 判斷hashcode值是否相同,如果不同,則不重覆
  2. 如果hashcode相同,調用equals比較,如果為true,則重覆。否則掛在元素下邊
  3. 在類中可以重寫equals和hashCode方法,進行自定義特征比較
//假設這是一個學生類,有name和age兩個屬性
//重寫equals和hashCode方法
@Override 
public boolean equals(Object o) { 
    if (this == o) 
        return true; 
    if (o == null || getClass() != o.getClass()) 
        return false; 
    Student student = (Student) o; 
    return Objects.equals(name, student.name); //例如這裡
    //可以自定義比較對象中的哪一個特征,比如就比較名字是否一樣,不在乎年齡是否一樣
} 
@Override 
public int hashCode() { 
    return Objects.hash(name); //例如這裡
    //可以自定義要進行計算哈希的對象,比如只想判斷名字哈希是否一樣,
    //名字哈希一樣就認為這倆對象哈希一樣,不在乎年齡哈希是否一樣
}

3. TreeSet

3.1 特點:預設自然升序排序,不重覆,無索引,可排序

3.2 排序方式

  • 自然排序

  1. 必須實現Comparable介面,重寫compareTo,定義排序規則
  2. Integer、String這些類預設已經實現了Comparable介面,可以直接去調用
  3. 英文按照字母順序,中文按照Unicode碼大小升序
  • 比較器排序(定製排序):

  創建集合時候就實現Comparator介面

  如何理解排序呢

  首先要知道這倆的區別

  • Comparable是比較介面,Comparator是比較器
  • 實現比較介面(Comparable)就意味著該類支持排序
  • 實現比較器(Comparator)就意味著該集合要使用自定義的比較方法
  • Comparable相當於“內部比較器”,而Comparator相當於“外部比較器”。

  通俗一點,用人話說就是:

  • 使用Comparable就是支持排序,意思是我這個類支持排序
  • 使用了Comparator就是比較器,不管類支不支持,想要排序就得按照我比較器的規矩排序

LinkedHashSet

  1. 特點:有序(存入和取出順序一樣),不重覆,無索引
  2. 底層存儲結構:哈希表和雙向鏈表,雙向鏈表用來記錄存儲的順序

七、所有集合最全面總結

  List Set
實現類 ArrayList LinkedList HashSet TreeSet LinkedHashSet
順序 有序 有序 無序 有序 有序
重覆 可重覆 可重覆 不可重覆 不可重覆 不可重覆
空值 允許多個null 允許多個null 最多一個null 最多一個null 最多一個null
索引 有索引 有索引 無索引 無索引 無索引
排序 存入順序就是取出順序 存入順序就是取出順序 不能排序 自然排序和比較器排序 存入順序就是取出順序
特點 查詢快 增刪首尾操作快 增刪改查都快的五邊形戰士 唯一可以自定義排序 增刪改查都快的五邊形戰士
底層 數組 鏈表 哈希表 紅黑樹 哈希表和雙鏈表
凡是帶list都可重覆、有索引 凡是帶set都不可重覆、無索引
凡是帶hash都是五邊形戰士,增刪改查都快 只有HashSet無序、不能排序

八、集合工具類Collections

Collections 不屬於集合,是用來操作集合的工具類

 


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 多個路由通過路由器進行管理。 前端路由的概念和原理 (編程中的)路由(router)就是一組key-value對應關係,分為:後端路由和前端路由 後端路由指的是:請求方式、請求地址和function處理函數之間的對應關係 在SPA程式中,所有組件的展示和切換都在這唯一的一個頁面內完成,此時,不同組件 ...
  • 定義 如果希望動態給某個類添加一些屬性或者方法,但是你又不希望這個類派生的對象受到影響,那麼裝飾器模式就可以給你帶來這樣的體驗。 它的定義就是在不改變原對象的基礎上,通過對其進行包裝拓展,使得原有對象可以動態具有更多功能,從而滿足用戶的更複雜需求。 舉個例子,一部手機,你可以買各種花里胡哨的手機殼等 ...
  • 長期以來,我們一直聽說物聯網(IoT)將通過將日常設備連接到互聯網來改變我們的生活和工作方式。雖然物聯網的許多承諾似乎總是 "即將到來",但物聯網設備的激增已經創造了大量的數據,需要實時處理、存儲和分析。我已經說了很多年--實際上已經超過十年了--如果你的物聯網數據不及時、不准確、不具有可操作性,那 ...
  • 這篇文章主要描述硬體同步原語,它是由電腦硬體提供的一組原子操作。 我們常見的原語操作有CAS和FAA兩種。在某些情景下,我們可以使用它來替代鎖,從而更加安全高效的操作數據。 ...
  • 這篇文章主要關註分散式鎖,包括加鎖和解鎖的過程,鎖的用法,加鎖帶來的代價,對性能的影響以及如何避免死鎖。 ...
  • 1. 性能優化是圍繞工具展開的 1.1. 最重要的工具大都是Java開發工具包(JDK)自帶的 1.2. 查看應用程式性能時,首先應該考察的就是CPU時間 2. 操作系統工具 2.1. Unix系統 2.1.1. sar(System Accounting Report)及其組成工具 2.1.2.  ...
  • Java 比較(==, equals) 一、= = ==:比較兩個對象的引用是否是同一個地址 二、equals object中equals方法調用的就是==,可以在其他類中重寫該方法。 三、為什麼要重寫equals要重寫hashcode方法 因為散列集合插入對象時會進行判斷,先調用hashcode, ...
  • 大家好,我是3y啊。 大概不知道從什麼時候,「微服務」「分散式」這兩個詞又再次頻繁出現在我的視線里。 「微服務」「分散式」在我剛畢業的時候還是比較關註的,那時候還入門了一把SpringCloud,寫了一篇很長的文章,還是很頂的,有不少的大號都給我轉載了,在知乎又獲得了很多的贊。 那時候覺得懂「分散式 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...