這篇文章記錄了Collection集合,List集合,Set集合 在文章第七點總結了兩大系列集合的五種實現類的區別,有需要的小伙伴可以直接去查看 一、什麼是集合 集合是Java中存儲對象數據的一種容器 二、集合有什麼特點 大小不固定,類型也可以不固定(通常需要泛型約束) 集合只能存儲引用數據類型 集 ...
這篇文章記錄了Collection集合,List集合,Set集合
在文章第七點總結了兩大系列集合的五種實現類的區別,有需要的小伙伴可以直接去查看
一、什麼是集合
集合是Java中存儲對象數據的一種容器
二、集合有什麼特點
- 大小不固定,類型也可以不固定(通常需要泛型約束)
- 集合只能存儲引用數據類型
- 集合適合對容器中的元素進行增刪操作
三、體繫結構
Collection單列集合,每個元素(數據)只包含一個值。
Map雙列集合,每個元素包含兩個值(鍵值對)。
四、Collection
1. 什麼是Collection
官方的解釋:
- Collection是集合層次結構中的根介面。 集合表示一組對象,稱為其元素 。 有些集合允許重覆元素而其他集合則不允許。 有些是有序的,有些是無序的。
- JDK不提供此介面(Collection)的任何直接實現:它提供了更具體的子介面的實現,如 Set 和 List
- 此介面通常用於傳遞集合併在需要最大通用性的情況下對其進行操作。
說的通俗一點就是:
- Collection是根介面,所有集合都來自Collection
- jdk不提供該介面實現類對象,但提供了更具體的實現類
- 就好比父類和子類,你可以用父類對象接收一個子類的實例化對象
例如:Father f = new Sun(); // Sun類繼承了Father類
2. Collection的體繫結構
3. 常用方法
方法名稱 |
說明 |
|
把給定的對象添加到當前集合中 |
|
清空集合中所有的元素 |
|
把給定的對象在當前集合中出現的第一個位置刪除,如果刪除失敗返回false |
|
判斷當前集合中是否包含給定的對象 |
|
判斷當前集合是否為空 |
|
返回集合中元素的個數。 |
|
把集合中的元素,存儲到數組中 |
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);
}
註意事項:
- 迭代器只能使用一次
- next()移動指針到下一個元素,如果沒有拋異常
- hasNext()檢查下一個元素是否為空,但不移動指針
- 迭代器迭代元素越界出現: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. 特有方法
方法名稱 |
說明 |
註意 |
|
將給定的元素插入到指定位置 |
索引不能越界,否則報錯
|
|
返回該索引位置的元素,沒找到返回-1 |
|
|
對給定位置的元素進行替換 |
|
|
刪除指定位置的元素 |
|
|
返回特定元素在集合中最後一次出現的位置 |
沒找到返回-1 |
|
返回特定元素在集合中第一次出現的位置 |
|
|
List集合特有的迭代器 |
|
|
根據開始索引和結束索引(左閉右開)返回一個新的集合,該集合是原集合的子集 |
|
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);
併發修改異常總結
- 同一時間只能有一個對象操作集合
- 使用迭代器要保證集合不在改變
- 出現異常的原因:
- 迭代器在進行遍歷過程中,如果對數組進行操作,會導致迭代器的實際修改值和集合的預期修改值不對應,就會出異常
- 迭代器是一次性的,如果對集合進行操作,沒有及時更新迭代器就會引發異常
- 如何解決併發修改異常
- 使用普通for:用索引取值,同一時間只有一個對象對集合操作
- 使用列表迭代器ListIterator
3.2 ListIterator
- ListIterator的兩個遍歷方法
|
從前往後遍歷 |
|
從後往前遍歷,前提是先得從前往後遍歷一遍,讓迭代器指針走到末尾 |
List<String> list = new ArrayList<>();
ListIterator<String> listIterator = list.listIterator();
- ListIterator和Iterator的區別
- ListIterator每進行一次迭代都會把實際修改值重新賦值給預期修改值,但是Iterator不行
- 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底層存儲結構
- 當調用無參hashSet構造器,會預設創建一個長度為16的數組
- 添加元素,元素哈希值和數組長度根據哈希演算法計算元素存儲位置
- 判斷該位置是否為空,如果為空直接存數組
- 如果位置不為空,判斷哈希值,如果不同直接存鏈表
- 如果哈希值相同,判斷equals是否相同,如果不同直接存鏈表
- 如果都相同就不存
-
版本差異
jdk8之前:新元素占據舊元素位置,指向舊元素。當元素鏈表掛載元素過多會造成查詢性能下降。
jdk8之後:新元素掛在舊元素下麵。當鏈表長度超過8時,自動將鏈表轉換為紅黑樹,進一步提高性能
-
元素去重原理(面試會問)
- 判斷hashcode值是否相同,如果不同,則不重覆
- 如果hashcode相同,調用equals比較,如果為true,則重覆。否則掛在元素下邊
- 在類中可以重寫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 排序方式
-
自然排序
- 必須實現Comparable介面,重寫compareTo,定義排序規則
- Integer、String這些類預設已經實現了Comparable介面,可以直接去調用
- 英文按照字母順序,中文按照Unicode碼大小升序
-
比較器排序(定製排序):
創建集合時候就實現Comparator介面
如何理解排序呢
首先要知道這倆的區別
- Comparable是比較介面,Comparator是比較器
- 實現比較介面(Comparable)就意味著該類支持排序
- 實現比較器(Comparator)就意味著該集合要使用自定義的比較方法
- Comparable相當於“內部比較器”,而Comparator相當於“外部比較器”。
通俗一點,用人話說就是:
- 使用Comparable就是支持排序,意思是我這個類支持排序
- 使用了Comparator就是比較器,不管類支不支持,想要排序就得按照我比較器的規矩排序
LinkedHashSet
- 特點:有序(存入和取出順序一樣),不重覆,無索引
- 底層存儲結構:哈希表和雙向鏈表,雙向鏈表用來記錄存儲的順序
七、所有集合最全面總結
List | Set | ||||
實現類 | ArrayList | LinkedList | HashSet | TreeSet | LinkedHashSet |
順序 | 有序 | 有序 | 無序 | 有序 | 有序 |
重覆 | 可重覆 | 可重覆 | 不可重覆 | 不可重覆 | 不可重覆 |
空值 | 允許多個null | 允許多個null | 最多一個null | 最多一個null | 最多一個null |
索引 | 有索引 | 有索引 | 無索引 | 無索引 | 無索引 |
排序 | 存入順序就是取出順序 | 存入順序就是取出順序 | 不能排序 | 自然排序和比較器排序 | 存入順序就是取出順序 |
特點 | 查詢快 | 增刪首尾操作快 | 增刪改查都快的五邊形戰士 | 唯一可以自定義排序 | 增刪改查都快的五邊形戰士 |
底層 | 數組 | 鏈表 | 哈希表 | 紅黑樹 | 哈希表和雙鏈表 |
凡是帶list都可重覆、有索引 | 凡是帶set都不可重覆、無索引 | ||||
凡是帶hash都是五邊形戰士,增刪改查都快 | 只有HashSet無序、不能排序 |
八、集合工具類Collections
Collections 不屬於集合,是用來操作集合的工具類