日韩av黄I国产麻豆传媒I国产91av视频在线观看I日韩一区二区三区在线看I美女国产在线I麻豆视频国产在线观看I成人黄色短片

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 >

「 深入浅出 」集合List

發布時間:2025/3/21 62 豆豆
生活随笔 收集整理的這篇文章主要介紹了 「 深入浅出 」集合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倍(這個需要注意一下,面試經常考)

//添加元素e public boolean add(E e) {ensureCapacityInternal(size + 1);//將對應索引下的元素賦值為e:elementData[size++] = e;return true; } //得到最小擴容量 private void ensureCapacityInternal(int minCapacity) {//如果此時ArrayList是空數組,則將最小擴容大小設置為10:if (elementData == EMPTY_ELEMENTDATA) {minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity);}//判斷是否需要擴容:ensureExplicitCapacity(minCapacity); } //判斷是否需要擴容 private void ensureExplicitCapacity(int minCapacity) {//操作數+1modCount++;//判斷最小擴容容量-數組大小是否大于0:if (minCapacity - elementData.length > 0)//擴容:grow(minCapacity); } //ArrayList動態擴容的核心方法: private void grow(int minCapacity) {//獲取現有數組大小:int oldCapacity = elementData.length;//位運算,得到新的數組容量大小,為原有的1.5倍:int newCapacity = oldCapacity + (oldCapacity >> 1);//如果新擴容的大小依舊小于傳入的容量值,那么將傳入的值設為新容器大小:if (newCapacity - minCapacity < 0)newCapacity = minCapacity;//如果新容器大小,大于ArrayList最大長度:if (newCapacity - MAX_ARRAY_SIZE > 0)//計算出最大容量值:newCapacity = hugeCapacity(minCapacity);//數組復制:elementData = Arrays.copyOf(elementData, newCapacity); } //計算ArrayList最大容量: private static int hugeCapacity(int minCapacity) {if (minCapacity < 0)throw new OutOfMemoryError();//如果新的容量大于MAX_ARRAY_SIZE//將會調用hugeCapacity將int的最大值賦給newCapacityreturn (minCapacity > MAX_ARRAY_SIZE) ?Integer.MAX_VALUE :MAX_ARRAY_SIZE; }

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屬性,該屬性就是我們所保存的元素。

//獲取相應角標的元素: public E get(int index) {//檢查索引是否正確:checkElementIndex(index);//獲取索引所屬結點的 元素值:return node(index).item; } //獲取對應角標所屬于的結點: java.util.LinkedList.Node<E> node(int index) {//位運算:如果位置索引小于列表長度的一半,則從頭開始遍歷;否則,從后開始遍歷;if (index < (size >> 1)) {java.util.LinkedList.Node<E> x = first;//從頭結點開始遍歷:遍歷的長度就是index的長度,獲取對應的index的元素for (int i = 0; i < index; i++)x = x.next;return x;} else {//從集合尾結點遍歷:java.util.LinkedList.Node<E> x = last;//同樣道理:for (int i = size - 1; i > index; i--)x = x.prev;return x;} }

ArrayList和LinkedList的主要區別

  • ArrayList基于數組實現的,LinkedList是基于雙向鏈表實現的
  • ArrayList隨機訪問效率高,隨機插入、隨機刪除效率低,需要移動元素位置
    LinkedList隨機插入、隨機刪除效率高,隨機訪問效率低,因需要遍歷鏈表

好叻,搞完,溜了溜了
下一期為<集合Set>,敬請期待

近期推薦:

好人?壞人?做真實的人
「 優質資源 」收藏!最新精選優質資源!
java小心機(5)| 淺談類成員初始化順序

更多精彩內容,可閱讀原文

您的點贊、轉發是對我最大的支持!

?THANDKS

  • End -

一個立志成大腿而每天努力奮斗的年輕人

伴學習伴成長,成長之路你并不孤單!

總結

以上是生活随笔為你收集整理的「 深入浅出 」集合List的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。