文章目錄
List 集合代表一個元素有序 、可重複的集合,集合中每個元素都有其對應的順序索引 。 List 集合允許使用重複元素 , 可以通過索引來通路指定位置的集合元素 。 List 集合預設按元素的添加順序設定元素的索引 。
相比較父接口 Collection,由于 List 是有序集合 , 是以 List 集合裡增加 了一些根據索引來操作集合元素的方法。
- void add(int index, Object element): 将元素 element 插入到 List 集合的 index 處 。
- boolean addAll(int index, Collection c): 将集合 c 所包含的所有元素都插入到 List 集合的 index處。
- Object get(int index): 傳回集合 index 索引處的元素。
- int indexOf(Object 0): 傳回對象 。 在 List 集合中第 一次出現的位置索引。
- int lastlndexOf(Object 0): 返 回 對象 。 在 List 集合中最後 一 次出現的位置索引 。
- Object remove(int index): 删除并傳回 index 索引處的元素 。
- Object set(int index, Object element): 将 index 索引處的元素替換成 e lement 對象,傳回被替換的舊元素 。
- List subList(int fromIndex, int toIndex): 傳回從索引 fromlndex (包含)到索引 to Index (不包含)處所有集合元素組成的子集合。
所有 的 List 實作類都可以調用這些方法來操作集合元素。與 Set 集合相比, List 增加了根據索引來插入、替換和删除集合元素 的方法。除此之外 , Java 8 還為 List 接口添加了如下兩個預設方法 :
- void replaceAll(UnaryOperator operator): 根據 operator 指定的計算規則重新設定 List 集合的所有元素。
- void sort(Comparator c): 根據 Comparator 參數對 List 集合的元素排序 。
下面程式示範了 List 集合的正常用法:
ListTest.java
public class ListTest
{
public static void main(String[] args)
{
List books = new ArrayList();
// 向books集合中添加三個元素
books.add(new String("輕量級Java EE企業應用實戰"));
books.add(new String("瘋狂Java講義"));
books.add(new String("瘋狂Android講義"));
System.out.println(books);
// 将新字元串對象插入在第二個位置
books.add(1 , new String("瘋狂Ajax講義"));
for (int i = 0 ; i < books.size() ; i++ )
{
System.out.println(books.get(i));
}
// 删除第三個元素
books.remove(2);
System.out.println(books);
// 判斷指定元素在List集合中位置:輸出1,表明位于第二位
System.out.println(books.indexOf(new String("瘋狂Ajax講義"))); //①
//将第二個元素替換成新的字元串對象
books.set(1, new String("瘋狂Java講義"));
System.out.println(books);
//将books集合的第二個元素(包括)
//到第三個元素(不包括)截取成子集合
System.out.println(books.subList(1 , 2));
}
}
運作結果:

①行代碼處,程式試圖傳回新字元串對象在 List集合中的位置,實際上 List 集合中并未包含該字元串對象 。 因為 List 集合添加宇符串對象時 ,添加的是通過 new 關鍵宇建立的新字元串對象,①行代碼處也是通過 new 關鍵宇建立的新字元串對象,兩個字元串顯然不是同一個對象,但 List 的 indexOf 方法依然可以傳回 1 。
List 判斷兩個對象相等隻要通過 equals()方法比較傳回 true 即可 。
ListTest2.java
class A
{
public boolean equals(Object obj)
{
return true;
}
}
public class ListTest2
{
public static void main(String[] args)
{
List books = new ArrayList();
books.add(new String("輕量級Java EE企業應用實戰"));
books.add(new String("瘋狂Java講義"));
books.add(new String("瘋狂Android講義"));
System.out.println(books);
// 删除集合中A對象,将導緻第一個元素被删除
books.remove(new A()); // ①
System.out.println(books);
// 删除集合中A對象,再次删除集合中第一個元素
books.remove(new A()); // ②
System.out.println(books);
}
}
執行①行代碼時 ,程式試圖删除一個 A 對象 , List 将會調用該A對象的equals()方法依次與集合元素進行比較,如果該 equalsO方法 以某個集合元素作為參數時傳回 true , List将會删除該元素——A 類重寫了 equalsO方法 , 該方法總是傳回 true。所 以每次從 List 集合中删除 A 對象時 ,總是删除 List 集合中的第一個元素 。
與 Set 隻提供了 一個 iterator()方法不同, List 還額外提供了 一個 listIterator()方法,該方法傳回 一個Listlterator 對象, ListIterator 接口繼承了Iterator 接口,提供了專門操作 List 的方法 。 ListIterator 接口在Iterator 接口基礎上增加了如下方法 。
- boolean hasPreviousO: 傳回該法代器關聯的集合是否還有上一個元素 。
- Object previous(): 傳回該疊代器的上一個元素。
- void add(Object 0): 在指定位置插入一個元素 。
API: java.util.List java.util.ListIterator
ArrayList結構圖
ArrayList 和 Vector 類都是基于數組實作的 List 類,是以 ArrayList 和 Vector 類封裝了一個動态的、允許再配置設定的 Object[]數組 。 ArrayList 或 Vector 對象使用 initialCapacity 參數來設定該數組的長度, 當向 ArrayList 或 Vector 中添加元素超出了該數組的長度時,它們的 initialCapacity 會自動增加 。
ArrayList構造方法
public ArrayList(int initialCapacity) {
if (initialCapacity > 0) {
// 如果傳入的初始容量大于0,就建立一個數組存儲元素
this.elementData = new Object[initialCapacity];
} else if (initialCapacity == 0) {
// 如果傳入的初始容量等于0,使用空數組EMPTY_ELEMENTDATA
this.elementData = EMPTY_ELEMENTDATA;
} else {
// 如果傳入的初始容量小于0,抛出異常
throw new IllegalArgumentException("Illegal Capacity: " + initialCapacity);
}
}
對于通常的程式設計場景,程式員無須關心 ArrayList 或 Vector 的 initialCapacity 。 但如果向ArrayList或 Vector 集合中添加大 量 元素時,可使用ensureCapacity(int minCapacity) 方法一次性地增加initialCapacity 。 這可以減少重配置設定 的 次數 ,進而提高性能 。
如果開始就知道 ArrayList 或 Vector 集合需要儲存多少個元素,則可以在建立它們時就指定initialCapacity 大小 。 如果建立空的 ArrayList 或 Vector 集合時不指定 initialCapacity 參數 ,則 Object[] 數組的長度預設為 10 。
ArrayList屬性
/**
* 預設容量
*/
private static final int DEFAULT_CAPACITY = 10;
/**
* 空數組,如果傳入的容量為0時使用
*/
private static final Object[] EMPTY_ELEMENTDATA = {};
/**
* 空數組,傳傳入容量時使用,添加第一個元素的時候會重新初始為預設容量大小
*/
private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};
/**
* 存儲元素的數組
*/
transient Object[] elementData; // non-private to simplify nested class access
/**
* 集合中元素的個數
*/
private int size;
除此之外,ArrayList 和 Vector 還提供了如下兩個方法來重新配置設定 Object[]數組:
- void ensureCapacity(int minCapacity): 将 ArrayList 或 Vector 集合的 Object[]數組長度增加大于或等于 minCapacity 值。
- void trimToSize(): 調整 ArrayList 或 Vector 集合 的 Object[]數組長度為 目前元素 的個數 。 調用該方法可減少 ArrayList 或 Vector 集合對象占用 的存儲空間 。
ArrayList 和 Vector 在用法上幾乎完全相同 ,Vector十分古老,那時候 Java 還沒有提供系統的集合架構,是以 Vector 裡提供了 一 些方法名很長的方法。
除此之外, ArrayList 和 Vector 的 顯著差別是 :
ArrayList 是線程不安全的,當多個線程通路同一個ArrayList 集合時,如果有超過一個線程修改了 ArrayList 集合,則程式必須于動保證該集合的同步性;
但 Vector 集合則是線程安全的,無須程式保證該集合的同步性。因為 Vector 是線程安全的,是以 Vector的性能比 ArrayList 的性能要低 。
java.util.ArrayList java.util.Vector
LinkedList結構圖
LinkedList 類是 List 接口的實作類 一它是一 個 List 集合 ,可以根據索引來随機通路集合中的元素 。
除此之外, LinkedList 還實作了 Deque 接口,可以被當成雙端隊列來使用,還可以被當成"棧"來使用 。
下面程式簡單示範了 LinkedList 集合的用法:
LinkedListTest.java
public class LinkedListTest
{
public static void main(String[] args)
{
LinkedList books = new LinkedList();
// 将字元串元素加入隊列的尾部
books.offer("瘋狂Java講義");
// 将一個字元串元素加入棧的頂部
books.push("輕量級Java EE企業應用實戰");
// 将字元串元素添加到隊列的頭部(相當于棧的頂部)
books.offerFirst("瘋狂Android講義");
// 以List的方式(按索引通路的方式)來周遊集合元素
for (int i = 0; i < books.size() ; i++ )
{
System.out.println("周遊中:" + books.get(i));
}
// 通路、并不删除棧頂的元素
System.out.println(books.peekFirst());
// 通路、并不删除隊列的最後一個元素
System.out.println(books.peekLast());
// 将棧頂的元素彈出“棧”
System.out.println(books.pop());
// 下面輸出将看到隊列中第一個元素被删除
System.out.println(books);
// 通路、并删除隊列的最後一個元素
System.out.println(books.pollLast());
// 下面輸出:[輕量級Java EE企業應用實戰]
System.out.println(books);
}
}
LinkedList 與 ArrayList 的實作機制完全不同:
- ArrayList 内部以數組的形式來儲存集合中的元素 , 是以随機通路集合元素時有較好的性能;
- 而 LinkedList 内部以連結清單的形式來儲存集合中的元素,是以随機通路集合元素時性能較差,但在插入、删除元素時性能比較出色(隻需改變指針所指的位址即可)。
雙向連結清單
從連結清單删除元素
java.util.LinkedList
參考
【1】:《瘋狂Java講義》
【2】:《Java核心技術 卷一》
【3】:
Java技術驿站:【死磕 Java 集合】— ArrayList源碼分析【4】:
方志朋的專欄:Java基礎:Java容器之ArrayList【5】:
Java技術驿站:【死磕 Java 集合】— LinkedList源碼分析【6】:
方志朋的專欄:Java基礎:Java容器之LinkedList【7】:
廖雪峰的官方網站:使用List