「 深入浅出 」集合List
第一篇文章?「 深入淺出 」java集合Collection和Map?主要講了對集合的整體介紹,本篇文章主要講List相對于Collection新增的一些重要功能以及其重要子類ArrayList、LinkedList、Vector
一、List集合
關于List集合的介紹與方法,可參考第一篇文章?「 深入淺出 」java集合Collection和Map
迭代方法ListIterator
相對于其它集合,List集合添加了一種新的迭代方法ListIterator
ListIterator的方法如下:
ListIterator接口在Iterator接口基礎上增加了如下方法:
boolean hasPrevious(): 如果以逆向遍歷列表。如果迭代器有上一個元素,則返回 true。
E previous():返回迭代器的前一個元素。
void add(Object o):將指定的元素插入列表。
int nextIndex():下一個索引號
int previousIndex():上一個索引號
void set(E e):修改迭代器當前元素的值
void add(E e):在迭代器當前位置插入一個元素
ListIterator接口比Iterator接口多了兩個功能:
1.ListIterator可在遍歷過程中新增和修改
2.ListIterator可逆向遍歷
使用示例如下:
public class ListIteratorDemo {public static void main(String[] args) {// 創建列表List<Integer> list = new ArrayList<Integer>();// 向列表中增加10個元素for (int i = 0; i < 10; i++) {list.add(i);}// 獲得ListIterator對象ListIterator<Integer> it = list.listIterator();// 正序遍歷修改與新增while (it.hasNext()) {Integer i = it.next();//修改元素值it.set(i+1);if(i == 5 ){//新增元素值it.add(55);}//! it.set(i+1);// 注意:如果修改的代碼在這個位置會報錯//set操作不能放在add操作之后// 這里不做解析,欲知詳情,請看源碼}System.out.println("正向遍歷");//正向遍歷for(Integer i:list){System.out.println(i+" ");}System.out.println("逆向遍歷");//逆向遍歷//經過上面迭代器it遍歷后,迭代器it已到達最后一個節點while (it.hasPrevious()) {System.out.println(it.previous() + " ");}} }二、ArrayList和Vector
ArrayList和Vector很相似,所以就一起介紹了
ArrayList和Vector類都是基于數組實現的List類,所以ArrayList和Vector類封裝了一個動態的、允許再分配的Object[]數組。ArrayList和Vector對象使用initalCapacity參數來設置該數組的長度,當向ArrayList和Vector中添加元素超過了該數組的長度時,它們的initalCapacity會自動增加。
下面我們通過閱讀JDK 1.8 ArrayList源碼來了解ArrayList
無參構造函數
默認初始化為容量為10
???/*** Constructs an empty list with an initial capacity of ten。意思是:構造一個空數組,默認的容量為10*/public ArrayList() {this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;}有參構造函數
創建指定容量的ArrayList
//動態Object數組,用來保存加入到ArrayList的元素 Object[] elementData;//ArrayList的構造函數,傳入參數為數組大小 public ArrayList(int initialCapacity) {if (initialCapacity > 0) {//創建一個對應大小的數組對象this.elementData = new Object[initialCapacity];} else if (initialCapacity == 0) {//傳入數字為0,將elementData 指定為一個靜態類型的空數組this.elementData = EMPTY_ELEMENTDATA;} else {throw new IllegalArgumentException("Illegal Capacity: "+initialCapacity);}}add方法
執行add方法時,先確保容量足夠大,若容量不夠,則會進行擴容;
擴容大小為原來的1.5倍(這個需要注意一下,面試經常考)
remove方法
有以下兩種刪除方法:
- remove(int index)是針對于索引來進行刪除,不需要去遍歷整個集合,效率更高;
- remove(Object o)是針對于對象來進行刪除,需要遍歷整個集合進行equals()方法比對,所以效率較低;
不過,無論是哪種形式的刪除,最終都會調用System.arraycopy()方法進行數組復制操作,等同于移動數組位置,所以效率都會受到影響
//在ArrayList的移除index位置的元素 public E remove(int index) {//檢查索引是否合法:不合法拋異常rangeCheck(index);//操作數+1:modCount++;//獲取當前索引的value:E oldValue = elementData(index);//獲取需要刪除元素 到最后一個元素的長度,也就是刪除元素后,后續元素移動的個數;int numMoved = size - index - 1;//如果移動元素個數大于0 ,也就是說刪除的不是最后一個元素:if (numMoved > 0)// 將elementData數組index+1位置開始拷貝到elementData從index開始的空間System.arraycopy(elementData, index+1, elementData, index, numMoved);//size減1,并將最后一個元素置為nullelementData[--size] = null;//返回被刪除的元素:return oldValue; }//在ArrayList的移除對象為O的元素,不返回被刪除的元素: public boolean remove(Object o) {//如果o==null,則遍歷集合,判斷哪個元素為null:if (o == null) {for (int index = 0; index < size; index++)if (elementData[index] == null) {//快速刪除,和前面的remove(index)一樣的邏輯fastRemove(index);return true;}} else {//同理:for (int index = 0; index < size; index++)if (o.equals(elementData[index])) {fastRemove(index);return true;}}return false; }//快速刪除: private void fastRemove(int index) {//操作數+1modCount++;//獲取需要刪除元素 到最后一個元素的長度,也就是刪除元素后,后續元素移動的個數;int numMoved = size - index - 1;//如果移動元素個數大于0 ,也就是說刪除的不是最后一個元素:if (numMoved > 0)// 將elementData數組index+1位置開始拷貝到elementData從index開始的空間System.arraycopy(elementData, index+1, elementData, index, numMoved);//size減1,并將最后一個元素置為nullelementData[--size] = null; }get方法
通過elementData()方法獲取對應索引元素,在返回時候進行類型轉換
//獲取index位置的元素 public E get(int index) {//檢查index是否合法:rangeCheck(index);//獲取元素:return elementData(index); } //獲取數組index位置的元素:返回時類型轉換 E elementData(int index) {return (E) elementData[index]; }set方法
通過elementData獲取舊元素,再設置新元素值相應index位置,最后返回舊元素
//設置index位置的元素值了element,返回該位置的之前的值 public E set(int index, E element) {//檢查index是否合法:判斷index是否大于sizerangeCheck(index);//獲取該index原來的元素:E oldValue = elementData(index);//替換成新的元素:elementData[index] = element;//返回舊的元素:return oldValue; }調整容量大小
ArrayList還提供了兩個額外的方法來調整其容量大小
- void ensureCapacity(int minCapacity): 增加容量,以確保它至少能夠容納最小容量參數所指定的元素數。
- void trimToSize():將容量調整為列表的當前大小。
Vector實現原理與ArrayList基本相同,可參考上述內容
ArrayList和Vector的主要區別
- ArrayList是線程不安全的,Vector是線程安全的。
- Vector的性能比ArrayList差。
LinkedList
LinkedList是基于雙向鏈表實現的,內部存儲主要是Node對象,該對象存儲著元素值外,還指向上一節點和下一節點。
注意,因為LinkedList是基于鏈表實現的,沒有容量的說法,所以更沒有擴容之說
集合基礎框架
public class LinkedList<E>extends AbstractSequentialList<E>implements List<E>, Deque<E>, Cloneable, java.io.Serializable {//LinkedList的元素個數:transient int size = 0;//LinkedList的頭結點:Node內部類transient java.util.LinkedList.Node<E> first;//LinkedList尾結點:Node內部類transient java.util.LinkedList.Node<E> last;//空實現:頭尾結點均為null,鏈表不存在public LinkedList() {}//調用添加方法:public LinkedList(Collection<? extends E> c) {this();addAll(c);}//節點的數據結構,包含前后節點的引用和當前節點private static class Node<E> {//結點元素:E item;//結點后指針java.util.LinkedList.Node<E> next;//結點前指針java.util.LinkedList.Node<E> prev;Node(java.util.LinkedList.Node<E> prev, E element, java.util.LinkedList.Node<E> next) {this.item = element;this.next = next;this.prev = prev;}} }LinkedList的常用方法只做簡單介紹不貼源碼,具體可自行看源碼
add方法
LinkedList有兩種添加方法
- add(E e)鏈表最后添加一個元素
- add(int index, E element)指定位置下添加一個元素;
LinedList添加元素主要分為以下步驟:
1.將添加的元素轉換為LinkedList的Node對象節點;
2.增加該Node節點的前后引用,即該Node節點的prev、next屬性,讓其分別指上、下節點;
3.修改該Node節點的前后Node節點中pre/next屬性,使其指向該節點。
remove方法
LinkedList的刪除也提供了2種形式
- remove(int index)直接通過索引刪除元素
- remove(Object o)通過對象刪除元素,需要逐個遍歷LinkedList的元素,重復元素只刪除第一個:
刪除后,需要修改上節點的next指向當前下一節點,下節點的prev指向當前上一節點
set方法
set(int index, E element)方法通過node(index)獲取到相應的Node,再修改元素的值
get方法
這是我們最常用的方法,其中核心方法node(int index),需要從頭遍歷或從后遍歷找到相應Node節點
在通過node(int index)獲取到對應節點后,返回節點中的item屬性,該屬性就是我們所保存的元素。
ArrayList和LinkedList的主要區別
- ArrayList基于數組實現的,LinkedList是基于雙向鏈表實現的
- ArrayList隨機訪問效率高,隨機插入、隨機刪除效率低,需要移動元素位置
LinkedList隨機插入、隨機刪除效率高,隨機訪問效率低,因需要遍歷鏈表
好叻,搞完,溜了溜了
下一期為<集合Set>,敬請期待
近期推薦:
好人?壞人?做真實的人
「 優質資源 」收藏!最新精選優質資源!
java小心機(5)| 淺談類成員初始化順序
更多精彩內容,可閱讀原文
您的點贊、轉發是對我最大的支持!
?THANDKS
- End -
一個立志成大腿而每天努力奮斗的年輕人
伴學習伴成長,成長之路你并不孤單!
總結
以上是生活随笔為你收集整理的「 深入浅出 」集合List的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: python数据结构与算法(13)
- 下一篇: 线程(Thread,ThreadPool