日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

「 深入浅出 」集合List

發(fā)布時(shí)間:2025/3/21 编程问答 55 豆豆
生活随笔 收集整理的這篇文章主要介紹了 「 深入浅出 」集合List 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

第一篇文章?「 深入淺出 」java集合Collection和Map?主要講了對(duì)集合的整體介紹,本篇文章主要講List相對(duì)于Collection新增的一些重要功能以及其重要子類ArrayList、LinkedList、Vector

一、List集合

關(guān)于List集合的介紹與方法,可參考第一篇文章?「 深入淺出 」java集合Collection和Map

迭代方法ListIterator

相對(duì)于其它集合,List集合添加了一種新的迭代方法ListIterator
ListIterator的方法如下:

ListIterator接口在Iterator接口基礎(chǔ)上增加了如下方法:
boolean hasPrevious(): 如果以逆向遍歷列表。如果迭代器有上一個(gè)元素,則返回 true。
E previous():返回迭代器的前一個(gè)元素。
void add(Object o):將指定的元素插入列表。
int nextIndex():下一個(gè)索引號(hào)
int previousIndex():上一個(gè)索引號(hào)
void set(E e):修改迭代器當(dāng)前元素的值
void add(E e):在迭代器當(dāng)前位置插入一個(gè)元素

ListIterator接口比Iterator接口多了兩個(gè)功能:
1.ListIterator可在遍歷過(guò)程中新增和修改
2.ListIterator可逆向遍歷

使用示例如下:

public class ListIteratorDemo {public static void main(String[] args) {// 創(chuàng)建列表List<Integer> list = new ArrayList<Integer>();// 向列表中增加10個(gè)元素for (int i = 0; i < 10; i++) {list.add(i);}// 獲得ListIterator對(duì)象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);// 注意:如果修改的代碼在這個(gè)位置會(huì)報(bào)錯(cuò)//set操作不能放在add操作之后// 這里不做解析,欲知詳情,請(qǐng)看源碼}System.out.println("正向遍歷");//正向遍歷for(Integer i:list){System.out.println(i+" ");}System.out.println("逆向遍歷");//逆向遍歷//經(jīng)過(guò)上面迭代器it遍歷后,迭代器it已到達(dá)最后一個(gè)節(jié)點(diǎn)while (it.hasPrevious()) {System.out.println(it.previous() + " ");}} }

二、ArrayList和Vector

ArrayList和Vector很相似,所以就一起介紹了

ArrayList和Vector類都是基于數(shù)組實(shí)現(xiàn)的List類,所以ArrayList和Vector類封裝了一個(gè)動(dòng)態(tài)的、允許再分配的Object[]數(shù)組。ArrayList和Vector對(duì)象使用initalCapacity參數(shù)來(lái)設(shè)置該數(shù)組的長(zhǎng)度,當(dāng)向ArrayList和Vector中添加元素超過(guò)了該數(shù)組的長(zhǎng)度時(shí),它們的initalCapacity會(huì)自動(dòng)增加。

下面我們通過(guò)閱讀JDK 1.8 ArrayList源碼來(lái)了解ArrayList

無(wú)參構(gòu)造函數(shù)

默認(rèn)初始化為容量為10

???/*** Constructs an empty list with an initial capacity of ten。意思是:構(gòu)造一個(gè)空數(shù)組,默認(rèn)的容量為10*/public ArrayList() {this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;}

有參構(gòu)造函數(shù)

創(chuàng)建指定容量的ArrayList

//動(dòng)態(tài)Object數(shù)組,用來(lái)保存加入到ArrayList的元素 Object[] elementData;//ArrayList的構(gòu)造函數(shù),傳入?yún)?shù)為數(shù)組大小 public ArrayList(int initialCapacity) {if (initialCapacity > 0) {//創(chuàng)建一個(gè)對(duì)應(yīng)大小的數(shù)組對(duì)象this.elementData = new Object[initialCapacity];} else if (initialCapacity == 0) {//傳入數(shù)字為0,將elementData 指定為一個(gè)靜態(tài)類型的空數(shù)組this.elementData = EMPTY_ELEMENTDATA;} else {throw new IllegalArgumentException("Illegal Capacity: "+initialCapacity);}}

add方法

執(zhí)行add方法時(shí),先確保容量足夠大,若容量不夠,則會(huì)進(jìn)行擴(kuò)容;
擴(kuò)容大小為原來(lái)的1.5倍(這個(gè)需要注意一下,面試經(jīng)常考)

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

remove方法

有以下兩種刪除方法:

  • remove(int index)是針對(duì)于索引來(lái)進(jìn)行刪除,不需要去遍歷整個(gè)集合,效率更高;
  • remove(Object o)是針對(duì)于對(duì)象來(lái)進(jìn)行刪除,需要遍歷整個(gè)集合進(jìn)行equals()方法比對(duì),所以效率較低;

不過(guò),無(wú)論是哪種形式的刪除,最終都會(huì)調(diào)用System.arraycopy()方法進(jìn)行數(shù)組復(fù)制操作,等同于移動(dòng)數(shù)組位置,所以效率都會(huì)受到影響

//在ArrayList的移除index位置的元素 public E remove(int index) {//檢查索引是否合法:不合法拋異常rangeCheck(index);//操作數(shù)+1:modCount++;//獲取當(dāng)前索引的value:E oldValue = elementData(index);//獲取需要?jiǎng)h除元素 到最后一個(gè)元素的長(zhǎng)度,也就是刪除元素后,后續(xù)元素移動(dòng)的個(gè)數(shù);int numMoved = size - index - 1;//如果移動(dòng)元素個(gè)數(shù)大于0 ,也就是說(shuō)刪除的不是最后一個(gè)元素:if (numMoved > 0)// 將elementData數(shù)組index+1位置開(kāi)始拷貝到elementData從index開(kāi)始的空間System.arraycopy(elementData, index+1, elementData, index, numMoved);//size減1,并將最后一個(gè)元素置為nullelementData[--size] = null;//返回被刪除的元素:return oldValue; }//在ArrayList的移除對(duì)象為O的元素,不返回被刪除的元素: public boolean remove(Object o) {//如果o==null,則遍歷集合,判斷哪個(gè)元素為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) {//操作數(shù)+1modCount++;//獲取需要?jiǎng)h除元素 到最后一個(gè)元素的長(zhǎng)度,也就是刪除元素后,后續(xù)元素移動(dòng)的個(gè)數(shù);int numMoved = size - index - 1;//如果移動(dòng)元素個(gè)數(shù)大于0 ,也就是說(shuō)刪除的不是最后一個(gè)元素:if (numMoved > 0)// 將elementData數(shù)組index+1位置開(kāi)始拷貝到elementData從index開(kāi)始的空間System.arraycopy(elementData, index+1, elementData, index, numMoved);//size減1,并將最后一個(gè)元素置為nullelementData[--size] = null; }

get方法

通過(guò)elementData()方法獲取對(duì)應(yīng)索引元素,在返回時(shí)候進(jìn)行類型轉(zhuǎn)換

//獲取index位置的元素 public E get(int index) {//檢查index是否合法:rangeCheck(index);//獲取元素:return elementData(index); } //獲取數(shù)組index位置的元素:返回時(shí)類型轉(zhuǎn)換 E elementData(int index) {return (E) elementData[index]; }

set方法

通過(guò)elementData獲取舊元素,再設(shè)置新元素值相應(yīng)index位置,最后返回舊元素

//設(shè)置index位置的元素值了element,返回該位置的之前的值 public E set(int index, E element) {//檢查index是否合法:判斷index是否大于sizerangeCheck(index);//獲取該index原來(lái)的元素:E oldValue = elementData(index);//替換成新的元素:elementData[index] = element;//返回舊的元素:return oldValue; }

調(diào)整容量大小

ArrayList還提供了兩個(gè)額外的方法來(lái)調(diào)整其容量大小

  • void ensureCapacity(int minCapacity): 增加容量,以確保它至少能夠容納最小容量參數(shù)所指定的元素?cái)?shù)。
  • void trimToSize():將容量調(diào)整為列表的當(dāng)前大小。

Vector實(shí)現(xiàn)原理與ArrayList基本相同,可參考上述內(nèi)容

ArrayList和Vector的主要區(qū)別

  • ArrayList是線程不安全的,Vector是線程安全的。
  • Vector的性能比ArrayList差。

LinkedList

LinkedList是基于雙向鏈表實(shí)現(xiàn)的,內(nèi)部存儲(chǔ)主要是Node對(duì)象,該對(duì)象存儲(chǔ)著元素值外,還指向上一節(jié)點(diǎn)和下一節(jié)點(diǎn)。
注意,因?yàn)長(zhǎng)inkedList是基于鏈表實(shí)現(xiàn)的,沒(méi)有容量的說(shuō)法,所以更沒(méi)有擴(kuò)容之說(shuō)

集合基礎(chǔ)框架

public class LinkedList<E>extends AbstractSequentialList<E>implements List<E>, Deque<E>, Cloneable, java.io.Serializable {//LinkedList的元素個(gè)數(shù):transient int size = 0;//LinkedList的頭結(jié)點(diǎn):Node內(nèi)部類transient java.util.LinkedList.Node<E> first;//LinkedList尾結(jié)點(diǎn):Node內(nèi)部類transient java.util.LinkedList.Node<E> last;//空實(shí)現(xiàn):頭尾結(jié)點(diǎn)均為null,鏈表不存在public LinkedList() {}//調(diào)用添加方法:public LinkedList(Collection<? extends E> c) {this();addAll(c);}//節(jié)點(diǎn)的數(shù)據(jù)結(jié)構(gòu),包含前后節(jié)點(diǎn)的引用和當(dāng)前節(jié)點(diǎn)private static class Node<E> {//結(jié)點(diǎn)元素:E item;//結(jié)點(diǎn)后指針java.util.LinkedList.Node<E> next;//結(jié)點(diǎn)前指針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的常用方法只做簡(jiǎn)單介紹不貼源碼,具體可自行看源碼

add方法

LinkedList有兩種添加方法

  • add(E e)鏈表最后添加一個(gè)元素
  • add(int index, E element)指定位置下添加一個(gè)元素;

LinedList添加元素主要分為以下步驟:
1.將添加的元素轉(zhuǎn)換為L(zhǎng)inkedList的Node對(duì)象節(jié)點(diǎn);
2.增加該Node節(jié)點(diǎn)的前后引用,即該Node節(jié)點(diǎn)的prev、next屬性,讓其分別指上、下節(jié)點(diǎn);
3.修改該Node節(jié)點(diǎn)的前后Node節(jié)點(diǎn)中pre/next屬性,使其指向該節(jié)點(diǎn)。

remove方法

LinkedList的刪除也提供了2種形式

  • remove(int index)直接通過(guò)索引刪除元素
  • remove(Object o)通過(guò)對(duì)象刪除元素,需要逐個(gè)遍歷LinkedList的元素,重復(fù)元素只刪除第一個(gè):

刪除后,需要修改上節(jié)點(diǎn)的next指向當(dāng)前下一節(jié)點(diǎn),下節(jié)點(diǎn)的prev指向當(dāng)前上一節(jié)點(diǎn)

set方法

set(int index, E element)方法通過(guò)node(index)獲取到相應(yīng)的Node,再修改元素的值

get方法

這是我們最常用的方法,其中核心方法node(int index),需要從頭遍歷或從后遍歷找到相應(yīng)Node節(jié)點(diǎn)
在通過(guò)node(int index)獲取到對(duì)應(yīng)節(jié)點(diǎn)后,返回節(jié)點(diǎn)中的item屬性,該屬性就是我們所保存的元素。

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

ArrayList和LinkedList的主要區(qū)別

  • ArrayList基于數(shù)組實(shí)現(xiàn)的,LinkedList是基于雙向鏈表實(shí)現(xiàn)的
  • ArrayList隨機(jī)訪問(wèn)效率高,隨機(jī)插入、隨機(jī)刪除效率低,需要移動(dòng)元素位置
    LinkedList隨機(jī)插入、隨機(jī)刪除效率高,隨機(jī)訪問(wèn)效率低,因需要遍歷鏈表

好叻,搞完,溜了溜了
下一期為<集合Set>,敬請(qǐng)期待

近期推薦:

好人?壞人?做真實(shí)的人
「 優(yōu)質(zhì)資源 」收藏!最新精選優(yōu)質(zhì)資源!
java小心機(jī)(5)| 淺談?lì)惓蓡T初始化順序

更多精彩內(nèi)容,可閱讀原文

您的點(diǎn)贊、轉(zhuǎn)發(fā)是對(duì)我最大的支持!

?THANDKS

  • End -

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

伴學(xué)習(xí)伴成長(zhǎng),成長(zhǎng)之路你并不孤單!

總結(jié)

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

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。