概述
之前學的ArrayList就是集合的一種,是一種容器,可以往里面存東西,大小可變
Collection集合體系
Collection的常用方法
以后Collection體系的集合都可以用下圖的方法
注意
toArray方法的數組類型是Object,這樣就可以接收任意類型的數據到數組中去,如果需要指定數組類型,方法如下圖
補充
addAll( ) 方法,可以將一個集合中的數據拷貝一份到另一個集合中去,示例如下圖
?輸出結果===>? ? ?
Collection的遍歷方式
之后所有的Collection體系集合都能使用這些方法,而之前用的for方法本質是利用 i 充當索引進行遍歷的,而Set系列集合是沒有索引的,只能在List系列集合中使用
迭代器
(是不是有點像鏈表的遍歷🤔,不準確理解方式:next指向當前所在元素,獲取后就指向下一個元素,使用hasnext判斷指向元素是否為空)
示例:
增強for循環
示例:ele可以取任何名字,把ele理解成當前指向的元素,他會遍歷完所有的元素
Lambda表達式
Java提供一個foreach方法用于遍歷,可以采用lambda表達式簡化,目前還看不出其強大的簡化能力,當后面學到對map集合遍歷時,才能感受到他的強大之處
List集合
未來創建ArrayList或LinkList推薦采用多態的寫法:List<類型> 類名 = new ArrayList<>( );? 或??List<類型> 類名 = new LinkedList<>( );
ArrrayList與LinkedList的底層實現不同,采用的數據結構不一樣,適用場景不同
List特有方法
List遍歷方式
有索引,因此是支持普通的for循環的
ArrayList
底層原理
應用場景
ArrayList? 適用于根據索引查數據、或數據量不大時;不適用于數據量大且需要頻繁進行增刪操作的場景
LinkedList
底層原理
應用場景
Set集合
HashSet用的比較多
前置知識-哈希值
每個對象都有一個哈希值,可以通過哈希值找到對象,若出現相同的哈希值-->碰撞(類比數據結構中的哈希查找)
哈希碰撞:
String類的hashCode()方法把字符值代入特定公式計算哈希值,知道公式就能輕易設計出哈希碰撞
上圖的例子是故意設計的,是為了演示哈希碰撞,實際中并不會這么容易就撞
HashSet
無序、不重復、無索引
jdk8之前:采用的是哈希表,因此增刪改查效率都不錯
補充知識
- 數組長度 × 加載因子 = 需要擴容的大小。比如上圖,16×0.75=12,當數組中占了12個位置的時候,就會進行擴容,增加數組長度至原來長度的兩倍
- 從jdk8開始,當鏈表的長度>8,且數組長度>=64,自動將鏈表轉換成紅黑樹(具體紅黑樹細節看408筆記)
去重機制
HashSet默認不能對內容一樣的兩個不同對象進行去重!因為雖然內容一樣,但是地址是不同的,因此HashSet會認為兩個對象并不是重復的
解決辦法:在對象的類中重寫 equals方法 與 HashCode方法 即可,直接右鍵generate可以生成,具體如下,簡單的理解 ---> 重寫后的equals方法:若對象相同會返回true,而重寫后的hashcode方法:若兩個對象的內容一樣就返回相同的哈希值
LinkedHashSet
有序、不重復、無索引
如何實現有序?雙鏈表實現,但也因此增加了內存
TreeSet
不重復、無索引、可排序
自定義排序規則
由于無法進行排序,因此需要自己指定排序規則,如下圖,之前在學習Arrays.sort時學過,這里方法一樣
補充:
- 如果兩種方法都是用了,TreeSet會采用就近原則使用外部重寫的Comparator規則,而不使用對象類內部重新的
- 如果兩個對象中出現的某一項相同,比如采用年齡排序,年齡都是16,則會丟失其中一個,因為Set的規則就是出現輸入相同的數據時會保留先前輸入的
Comparable
讓需要排序的對象類實現Comparable泛型接口,重寫comparetor,自己指定規則,就能對對象進行排序了,示例如下:
Comparator
Comparator是一個匿名內部類,在傳入參數時直接重寫,可以利用TreeSet的有參構造器直接設置Comparator對象
示例如下,其中調用的 Double.compare(double a,double b)?方法:a>b return 1 ; a<b return -1; a==b return0
各種集合的使用總結
注意事項
集合的并發修改異常問題
下面這段代碼就會發生并發修改異常問題,主要問題在于remove,remove后集合整體是會往前移一個的,因此當找到含李的名字的時候,remove后集合會整體往前移,此時hasNext會讓指針指向下一個,導致漏檢
解決辦法
若采用迭代器遍歷,不要直接使用? 集合.remove,而是采用? 迭代器.remove,就可以解決該問題
注意:若使用增強for循環或是lambda表達式進行循環出現并發修改異常問題,是沒有辦法解決的
其他相關知識
可變參數
示例:
Collections
addAll 示例:
shuffle 示例:
sort :
默認升序排序,如果里面存的是對象,就需要像上面一樣使用 comparable 或者 comparator 設置比較規則進行排序