Java中的集合List – 入門篇

前言

大家好啊,我是湯圓,今天給大家帶來的是《Java中的集合List – 入門篇》,希望對大家有幫助,謝謝

簡介

說實話,Java中的集合有很多種,但是這裡作為入門級別,先簡單介紹第一種集合List,如下圖所示

集合

正文

List是一種有序集合,和數組的行為非常相似,但是比數組靈活;

因為數組是長度固定的,而List的長度是動態分配的。

數組的概覽

既然LIst是基於數組實現的,那麼在介紹List之前,我們先來熟悉一下Java的數組吧(簡單過一下,畢竟用的不多了)

數組對象有一個length屬性來獲取數組的長度,和一個”[]”方法來訪問元素

數組也是一個對象,通過直接列印數組可以看出來,比如[Ljava.lang.String;@1b6d3586

如下所示,我們先初始化一個數組,並通過length訪問了數組的長度,[]語法訪問數組內的元素

// 初始化數組
String[] arr = {"1", "2", "3"};
// 數組長度
int length = arr.length;
// 數組第一個元素
String a1 = arr[0];
// 數組轉為字元串,需藉助Arrays工具類
String res = Arrays.toString(arr);

System.out.println(length);
System.out.println(a1);
System.out.println(res);

其中我們用到了Arrays這個工具類,因為數組的toString方法不能直接拼接內部的元素,而是列印數組對象的地址

List可以,直接調用List.toString()即可輸出所有元素拼接後的字元串

數組的優點:

隨機訪問快,也是僅存的一個優點(其他地方都沒ArrayList好)

數組的缺點

長度固定,插入慢

好了,數組先說到這裡,下面開始說List

List的介面方法

下面是幾個常用的List介面方法:

  • boolean add(E e):在列表末尾插入元素E

  • void add(int index, E element):在指定位置 index 插入元素 E

  • E get(int index):查詢指定位置 index 的元素

  • boolean contains(Object o):查詢列表是否包含指定的對象

  • boolean remove(Object o):刪除指定的對象

  • int size():查詢列表的元素個數

ArrayList和LinkedList的區別

用表格對比結果如下:

ArrayList LinkedList
內部結構 數組,有序 雙向鏈表,無序
隨機訪問
插入、修改 慢(如果是末尾插入,則很快)

可以看到,ArrayList適合隨機訪問,LinkedList適合插入和修改(如果是尾插,則區別不大)

為什麼ArrayList隨機訪問很快呢?

ArrayList是基於數組實現的,而數組又是基於整數索引(下標)來查詢數據的,所以ArrayList的查詢效率很高

為什麼ArrayList插入又很慢?

插入很慢,是因為ArrayList內部基於數組實現,記憶體都是連續的,因此插入時要移動後面的數據;

如果是直接在末尾插入,則不需要移動任何數據,也就快了(默認添加元素時,就是在尾部插入)

但是如果我要在中間位置插入,那麼後面的數據都需要移動

比如下圖,我想把 “Cat 005” 插入到 “Cat 001” 後面,那麼後面的 “Cat 002″、”Cat 003″、 “Cat 004″都要移動,這就導致效率很低

ArrayList中間插入圖

為什麼LinkedList隨機訪問慢?

因為LinkedList內部是雙向鏈表結構,即每個元素都包含一個前引用和後引用,如下圖所示

LinkedList內部結構

這就導致了一個問題,每次不管我訪問哪個元素,都需要從頭開始一個個索引;

結果就是訪問速度很慢。

那麼為什麼LinkedList隨機插入很快呢?

正所謂”成也蕭何敗蕭何”,雖然隨機訪問慢,但是正因為有了這些鏈表結構,使得插入的時候很方便了

因為現在不需要移動任何元素,只需要修改前後元素的引用就可以了

比如下圖,我想把 “Dog 005” 插入到 “Dog 001” 後面,那麼只需要修改 “Dog 001″的後引用和”Dog 002″的前引用,其他元素都不用動的

LinkedList中間插入圖

細心的你們可能發現了,ArrayList圖中的元素都是順序排列的,而LinkedList圖中的元素都是隨機排列的;

這個其實就是為了說明他們倆的內部結構特徵,ArrayList記憶體空間有序,LinkedList記憶體空間無序

那麼LinkedList這樣設計,除了插入快,還有其他好處嗎?

當然有啊,因為LinkedList內部的數據都是通過引用來連接到一起的,所以就可以很好的利用零散的記憶體空間,從而提高記憶體利用率

程式碼

下面我們用程式碼來實踐下

// 初始化
List<String> list = new ArrayList<>();
// 插入數據
list.add("hello world 1");
// 在指定位置插入數據
list.add(0, "hello world 2");
// 查詢數據
String s1 = list.get(0);
// 查詢List是否包含指定對象
boolean isContain = list.contains(s1);
// 查詢列表的元素個數
int size = list.size();
// 列印list內部元素:
String res = list.toString();

結果如下所示,可以看到,List.toString()會自動拼接內部元素

List程式碼輸出

總結

List是一種有序集合,和數組的行為非常相似,但是比數組靈活;

最常用的是ArrayList,它適用於大部分場景;

但是在插多查少的情況下,建議用LinkedList,可以提高插入的效率;

後記

最後,感謝大家的觀看,謝謝

Tags: