在前面,我們講完了JavaSE的基礎語法部分,現在我們就來開始學習JavaSE最后很重要的一部分:集合,這一塊,面試官也會經常問到,比如JDK1.8后,HashMap底層是如何實作的…… 話不多說,我們來看一下今天的主題:List, 在講解List之前,我們先來看一下JavaSE集合的大致框架,分別包含了哪些集合,以及每個集合背后所多余的資料結構是什么,


以上全部就是JavaSE中的所有集合,后面的文章都是圍繞這張圖進行講解,
前期文章:
前言- IDEA如何配置?讓你敲代碼更輕松!
初識Java語言(一)- 基本資料型別及運算子
初識Java語言(二)- 方法以及遞回
初識Java語言(三)- 陣列
初識Java語言(四)-類和物件
初識Java語言(五)- 包和繼承
初識Java語言(六)-多型、抽象類以及介面
初識Java語言(七)- String、StringBuilder和StringBuffer的區別
初識Java語言(八)- 例外
文章目錄
- 一、初始泛型(Generic)
- 二、包裝類
- 三、Stack
- 四、ArrayList
- 五、LinkedList
- 六、Queue
- 七、Deque
一、初始泛型(Generic)
在前期我們學習JavaSE基礎語法部分時,自己寫的所有的類,都是固定了里面的元素型別,比如自己寫的順序表時,都是固定了寫int型別,這樣寫本身是沒有什么錯的,但是不夠通用,說的簡單一點,假設現在我需要一個double型別的順序表,只能自己重新在寫一個類,很麻煩,
所以Java底層也是考慮到了這個情況,才引入了泛型(Generic),顧名思義,泛型就是廣泛的型別,其語法格式為: <型別>, 用一對尖括號,里面寫著的就是型別名,將這個整體寫到類的后面,我們才實體化這個類時,就可以給定相應的資料型別,如下:

//具體的使用方法
ArrayList<Integer> list = new ArrayList<>();
像上面這樣,我們就實體化了一個順序表,就可以在list里面進行順序表的相關操作,
泛型,既有泛型類,也有泛型方法,這里我們只是初始泛型,具體的細節,我們會在后面專門來講解這個,
泛型背后作用時期和背后的簡單原理:
- 泛型是作用在編譯期間的一種機制,也就是說在運行期間是沒有泛型這個概念的,
泛型總結
- 泛型是為了解決某些容器、演算法等代碼的通用性而引入的,并且能在編譯期間做型別檢查,
- 泛型是利用Object是所有類的祖先類,并且父類的參考可以指向子類物件的特定而作業,
- 泛型只是編譯期間的一種機制,也就是說
ArrayList<String>和ArrayList<Integer>是同一種型別, - 泛型是Java中一種合法的語法,標志是<>.
- 泛型里面寫的型別,必須是參考型別,基本資料型別,應書寫相應的包裝類,比如:int,寫成泛型是
<Integer>,
二、包裝類
我們都是到java有8種基本資料型別,int、double等等,他們都是基本資料型別,我們前面文章講過,除了基本資料型別以外,還有一個參考資料型別,而基本資料型別,每一個都有對應的包裝類,這個包裝類就是參考資料型別的,

如上圖,8種基本資料型別所對應的包裝類,除了char和int,其余的包裝類,都是在原基礎之上,將首字母大寫即可,每一個包裝類中,都有相應的方法可以使用,這里舉一個例子:

包裝類,能夠拿到相應基本資料型別最大值和最小值等等,具體的,可以查看幫助手冊,
自動裝箱和自動拆箱
裝箱:從基本資料型別的資料,轉換為包裝類的資料,拆箱反之,在使用程序中,java提供了自動機制,,如下代碼:
int a = 10;
Integer aa = a; //自動裝箱
Integer aaa = (Integer)a; //自動裝箱
int b = aa; //自動拆箱
int bb = (int)aa; //自動拆箱
注:自動裝箱和自動拆箱只是在編譯期間的一種機制, 我們可以通過javap -c 類名進行反編譯,查看底層是如何進行編譯的,
三、Stack
Stack,是Java底層實作的一個堆疊,堆疊的特性:先進后出,

//實體化
Stack<String> stack = new Stack<>();
stack.push("hello world"); //將字串壓入堆疊
String str1 = stack.peek(); //回傳堆疊頂的元素,并不會洗掉堆疊頂元素
String str2 = stack.pop()l //將堆疊頂元素彈出堆疊,但是會洗掉堆疊頂元素,注意與peek的區別
boolean flag = stack.empty(); //判斷堆疊的是否還有元素
以上就是Stack,最基本的的使用操作,也比較簡單,反反復復就是這些操作,
四、ArrayList
ArrayList,底層是一個順序表,也就是一個陣列,那我們來看一下,這個底層大致是怎么實作的?

由圖可知,add方法默認是將元素放到陣列的最后的!
接下來分析ArrayList的實作:

看圖,實體化ArrayList的時候,是賦值了一個空陣列,那么為什么在往里面添加元素的時候,沒有報例外呢?我們接著來看一下add方法,
add方法:

總結:在實體化ArrayList的時候,呼叫無參的構造方法,構造的是一個沒有容量的空陣列,而只有在第一次添加元素的時候,add方法才會進行擴容(1.5倍),然后當ArrayList陣列滿了之后,add方法就會再次以1.5倍進行擴容,
以下就是ArrayList一些常用的方法:

//常用方法示例
ArrayList<Integer> list = new ArrayList<>();
list.add(1);
list.add(2);
list.add(2,3); //在下標為2的位置,插入元素3
System.out.println(list.contains(3)); //查詢list中,是否有3這個元素
System.out.println(list.get(2)); //回傳下標為2的元素,常用
int index = list.indexOf(3); //回傳元素3,在表中第一次出現的位置,回傳值是下標
list.remove(index); //洗掉index位置的元素
int size = list.size(); //回傳當前list表中的元素個數
ArrayList中,底層是陣列,那么從中間插入、洗掉元素,都是需要移動陣列后面的元素的,跟陣列的操作一模一樣的,所以ArrayList這種集合,更適合于插入洗掉少的,但是查詢次數比較多的場景,查詢時間復雜度O(1),而插入洗掉操作時間復雜度O(N),
五、LinkedList
講完了ArrayList,現在就來講解與之對應的LinkedList,LinkedList底層是一個雙鏈表,如下:

雙鏈表應該就不用多說了吧,即可以在頭部插入洗掉,也可以在尾部插入洗掉,是一種比較靈活的資料結構,我們具體來看一下一些常用的方法:

圖中紅色框中,是使用LinkedList經常使用到的方法,無需記憶,用多了就記住了,
LinkedList<Integer> list = new LinkedList<>();
list.add(1); //在末尾添加元素
list.addFirst(10); //在頭部添加元素
list.addLast(11); //在末尾添加元素
int num1 = list.getFirst(); //拿到隊頭元素,不會洗掉
int num2 = list.getLast(); //拿到隊尾元素,不會洗掉
System.out.pritnln(list.contains(11)); //該表中是否有這個元素
//以下幾種方法,本質上就是堆疊和佇列中方法
int a = list.peek(); // 回傳隊頭元素,并不洗掉這個元素
int b = list.peekFirst(); // 回傳隊頭元素,并不洗掉這個元素
int c = list.peekLast(); //回傳隊尾元素,并不洗掉這個元素
int d = list.poll(); //彈出隊頭元素,并且會洗掉
int f = list.pollFirst(); //彈出隊頭元素,并洗掉
int g = list.pollLast(); //彈出隊尾元素,并洗掉
六、Queue
Queue是Java語言實作的一個佇列,滿足先進先出的特性,Queue是一個介面型別,不能直接進行實體化,我們需要實體化一個LinkedList,用Queue來參考,二者之間的關系,請看上文中的那個集合圖,
Queue<Integer> queue = new LinkedList<>();

圖中,add方法和offer方法,兩個方法都是在隊尾加入元素,功能是一樣的,在容量已滿的情況下,add() 方法會拋出IllegalStateException例外,offer() 方法只會回傳 false ,其他的方法,跟上面LinkedList中的方法差不多,remove方法,是洗掉隊頭的元素,而不是隊尾的元素,佇列是滿足先進先出的原則的,
七、Deque
Deque,雙端佇列,也就是說既可以在隊頭插入和洗掉,也可以在隊尾進行插入和洗掉,說白了,本質上還是一個LinkedList,只不過這是一個介面,實體化時,還是需要實體LinkedList,
Deque<Integer> deque = new LinkedList<>();

具體的方法,還是跟LinkedList差不多,只是可以在隊頭進行插入和洗掉,在隊尾進行插入和洗掉,有一些方法名有點差別而已,無非就是add、offer、poll、isEmpty、size等等,以及一些變形的名字,
好啦,本期更新就到此結束啦!這篇文章主要就是介紹了這些集合的一些方法,比較多,各位同學無需記憶,在日常刷演算法題的程序中,用多了,也就記住了,
好啦,我們下期見!!!
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/305958.html
標籤:java
上一篇:動態記憶體管理與柔性陣列
