學(xué)習(xí)Java中的List集合
1.概述
List
是一個有序集合(也被稱為序列)。此接口的用戶在列表中的每個元素都被插入的地方有精確的控制。用戶可以通過它們的整數(shù)索引(在列表中的位置)訪問元素,并在列表中搜索元素。 說是List集合,其實只是習(xí)慣說法,因為它是Collection接口的一個子接口(Collection有很多的子接口,這是其中三個主要的子接口之一,另外兩個后面都會說到),所以Collection
接口中定義的方法在List接口中也是可以使用的,另外還根據(jù)List的特點,又引入了其他的方法。
List接口的特點:
- 元素是以一種線性方式進(jìn)行存儲的
- 元素存取有序,即元素的存入順序和取出順序一致。
- 元素帶有索引,通過索引就可以精確的操作集合中的元素(與數(shù)組類似)
- 元素可以重復(fù),通過元素的equals方法,來比較是否為重復(fù)的元素
2.List的使用
2.1List的常用方法
基本介紹:
這里說的常用方法是指除了實現(xiàn)Collection
接口之外的。前面說到List集合中的元素是可以通過索引來操作集合中的元素的,所以List 集合里添加了一些根據(jù)索引來操作集合元素的方法。下面對這些方法進(jìn)行簡單
介紹:
void add(iint index, E element)
: 在列表中指定的位置上插入指定的元素boolean addAll(int index, Collection c)
: 將指定的集合中的所有元素插入到指定位置的列表中E get(int index)
:返回此列表中指定位置的元素List subList(int fromIndex, int toIndex)
:返回List中一部分對象的集合,即返回的集合是List的子集合,并是以下標(biāo)索引取值。父集合List以fromIndex開始(包含),到toIndex結(jié)束(不包含)的 部分為返回的子集合int indexOf(Object obj)
:返回此列表中指定元素的第一個出現(xiàn)的索引,如果此列表不包含元素,返回- 1int lastIndexOf(Object obj)
:返回此列表中指定元素的最后一個發(fā)生的索引,如果此列表不包含元素,返回- 1E remove(int index)
:移除此列表中指定位置的元素E set(int index, E element)
:用指定元素替換此列表中指定位置的元素
代碼示例:
public class ListDemo { ? ? public static void main(String[] args) { ?? ??? ?// 通過List的實現(xiàn)類ArrayList創(chuàng)建List集合對象 ? ? ?? ?List<String> list = new ArrayList<String>(); ? ? ?? ?// 指定位置添加元素 ? ? ?? ?list.add(0,"jack"); ? ? ?? ?list.add(1,"rose");?? ? ? ? ?? ?list.add(2,"marry");?? ??? ? ? ? ?? ?System.out.println(list); ? ? ?? ? ? ? ?? ?// 刪除索引位置為2的元素? ? ? ?? ?list.remove(2); ? ??? ? ? ? ?? ?System.out.println(list); ? ? ?? ? ? ? ?? ?// 指定元素替換此列表中指定位置的元素 ? ? ?? ?list.set(0, "老王"); ? ? ?? ?System.out.println(list); ? ? ?? ? ? ? ?? ?// 獲取指定位置元素(也遍歷輸出下)?? ? ? ? ?? ?for(int i = 0;i<list.size();i++){ ? ? ?? ??? ?System.out.println(list.get(i)); ? ? ?? ?} ? ? ?? ?//還可以使用增強(qiáng)for ? ? ?? ?for (String string : list) { ?? ??? ??? ?System.out.println(string); ?? ??? ?} ??? ? ?? ?} }
3.List的實現(xiàn)類
作為一個接口,List的實現(xiàn)類才是我們創(chuàng)建對象時候使用的(上面代碼示例里面用到了ArrayList實現(xiàn)類)。在List接口里,有三個常用的實現(xiàn)類:ArrayList、Vector、LinkedList。下面從源碼中分析和介紹它們。
3.1ArrayList
ArrayList
底層通過數(shù)組實現(xiàn),ArrayList
可以隨著元素的增加而動態(tài)擴(kuò)容。它是一個數(shù)組隊列,是Java集合框架中使用最多的一個類,但是它是線程不安全的。
- 特點:以數(shù)組的形式進(jìn)行存儲,因此隨機(jī)訪問速度較快,所有它適用于查詢
- 缺點:不適用于插入和刪除的操作 因為每次操作都需要移動數(shù)組中的元素;線程不安全
下面看下ArrayList的源碼:
public class ArrayList<E> extends AbstractList<E> ? ? ? ? implements List<E>, RandomAccess, Cloneable, java.io.Serializable{ ? ? /** ? ? ?* Default initial capacity. 初始化的時候如果沒有指定長度的話,使用默認(rèn)長度10 ? ? ?*/ ? ? private static final int DEFAULT_CAPACITY = 10; ? ?/** ? ? ?* Shared empty array instance used for empty instances. 空數(shù)組 ? ? ?*/ ? ? private static final Object[] EMPTY_ELEMENTDATA = {}; ? /** ? ? ?* Shared empty array instance used for default sized empty instances. We ? ? ?* distinguish this from EMPTY_ELEMENTDATA to know how much to inflate when ? ? ?* first element is added. ?空數(shù)組 ? ? ?*/ ? ? private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {}; /** ? ? ?* Constructs an empty list with an initial capacity of ten.構(gòu)造一個初始容量為10 ? ? ?*/ ? ? public ArrayList() { ? ? ? ? this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;//初始化為空數(shù)組 ? ? } ? ? public boolean add(E e) { ? ? ? ? //查看當(dāng)前數(shù)組是否夠多存一個元素 ? ? ? ? ensureCapacityInternal(size + 1); ?// Increments modCount!! ? ? ? ?? ? ? ? ? //存入新元素到[size]位置,然后size自增1 ? ? ? ? elementData[size++] = e; ? ? ? ? return true; ? ? } ? ? ? ?private void ensureCapacityInternal(int minCapacity) { ? ? ? ? ensureExplicitCapacity(calculateCapacity(elementData, minCapacity)); ? ? } ? ?private static int calculateCapacity(Object[] elementData, int minCapacity) { ? ?? ??? ? //如果當(dāng)前數(shù)組還是空數(shù)組 ? ? ? ? if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) { ? ? ? ? //那么minCapacity取DEFAULT_CAPACITY與minCapacity的最大值 ? ? ? ? ? ? return Math.max(DEFAULT_CAPACITY, minCapacity); ? ? ? ? } ? ? ? ? //查看是否需要擴(kuò)容 ? ? ? ? return minCapacity; ? ? ? } ? ?? ? ? private void ensureExplicitCapacity(int minCapacity) { ? ? ? ? modCount++;//修改次數(shù)加1 ? ? ? ? // 如果需要的最小容量比當(dāng)前數(shù)組的長度大,即當(dāng)前數(shù)組不夠存,就擴(kuò)容 ? ? ? ? if (minCapacity - elementData.length > 0) ? ? ? ? ? ? grow(minCapacity); ? ? } ? ? private void grow(int minCapacity) { ? ? ? ? // overflow-conscious code ? ? ? ? int oldCapacity = elementData.length;//當(dāng)前數(shù)組容量 ? ? ? ? int newCapacity = oldCapacity + (oldCapacity >> 1);//新數(shù)組容量是舊數(shù)組容量的1.5倍 ? ? ? ? //看舊數(shù)組的1.5倍是否夠 ? ? ? ? if (newCapacity - minCapacity < 0) ? ? ? ? ? ? newCapacity = minCapacity; ? ? ? ? //看舊數(shù)組的1.5倍是否超過最大數(shù)組限制 ? ? ? ? if (newCapacity - MAX_ARRAY_SIZE > 0) ? ? ? ? ? ? newCapacity = hugeCapacity(minCapacity); ? ? ? ?? ? ? ? ? //復(fù)制一個新數(shù)組 ? ? ? ? elementData = Arrays.copyOf(elementData, newCapacity); ? ?? ?} ? ?? ?public boolean remove(Object o) { ? ? ? ? //先找到o在當(dāng)前ArrayList的數(shù)組中的下標(biāo) ? ? ? ? //分o是否為空兩種情況討論 ? ? ? ? if (o == null) { ? ? ? ? ? ? for (int index = 0; index < size; index++) ? ? ? ? ? ? ? ? if (elementData[index] == null) {//null值用==比較 ? ? ? ? ? ? ? ? ? ? fastRemove(index); ? ? ? ? ? ? ? ? ? ? return true; ? ? ? ? ? ? ? ? } ? ? ? ? } else { ? ? ? ? ? ? for (int index = 0; index < size; index++) ? ? ? ? ? ? ? ? if (o.equals(elementData[index])) {//非null值用equals比較 ? ? ? ? ? ? ? ? ? ? fastRemove(index); ? ? ? ? ? ? ? ? ? ? return true; ? ? ? ? ? ? ? ? } ? ? ? ? } ? ? ? ? return false; ? ? } ? ? private void fastRemove(int index) { ? ? ? ? modCount++;//修改次數(shù)加1 ? ? ? ? //需要移動的元素個數(shù) ? ? ? ? int numMoved = size - index - 1; ? ? ? ?? ? ? ? ? //如果需要移動元素,就用System.arraycopy移動元素 ? ? ? ? if (numMoved > 0) ? ? ? ? ? ? System.arraycopy(elementData, index+1, elementData, index, ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?numMoved); ? ? ? ?? ? ? ? ? //將elementData[size-1]位置置空,讓GC回收空間,元素個數(shù)減少 ? ? ? ? elementData[--size] = null; // clear to let GC do its work ? ? } ? ? public E remove(int index) { ? ? ? ? rangeCheck(index);//檢驗index是否合法 ? ? ? ? modCount++;//修改次數(shù)加1 ? ? ? ?? ? ? ? ? //取出[index]位置的元素,[index]位置的元素就是要被刪除的元素,用于最后返回被刪除的元素 ? ? ? ? E oldValue = elementData(index); ? ? ? ?? ?? ??? ?//需要移動的元素個數(shù) ? ? ? ? int numMoved = size - index - 1; ? ? ? ?? ? ? ? ? //如果需要移動元素,就用System.arraycopy移動元素 ? ? ? ? if (numMoved > 0) ? ? ? ? ? ? System.arraycopy(elementData, index+1, elementData, index, ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?numMoved); ? ? ? ? //將elementData[size-1]位置置空,讓GC回收空間,元素個數(shù)減少 ? ? ? ? elementData[--size] = null; // clear to let GC do its work ? ? ? ? return oldValue; ? ? } ? ? public E set(int index, E element) { ? ? ? ? rangeCheck(index);//檢驗index是否合法 ? ? ? ? //取出[index]位置的元素,[index]位置的元素就是要被替換的元素,用于最后返回被替換的元素 ? ? ? ? E oldValue = elementData(index); ? ? ? ? //用element替換[index]位置的元素 ? ? ? ? elementData[index] = element; ? ? ? ? return oldValue; ? ? } ? ? public E get(int index) { ? ? ? ? rangeCheck(index);//檢驗index是否合法 ? ? ? ? return elementData(index);//返回[index]位置的元素 ? ? } ? ? ?public int indexOf(Object o) { ? ? ? ? //分為o是否為空兩種情況 ? ? ? ? if (o == null) { ? ? ? ? ? ? //從前往后找 ? ? ? ? ? ? for (int i = 0; i < size; i++) ? ? ? ? ? ? ? ? if (elementData[i]==null) ? ? ? ? ? ? ? ? ? ? return i; ? ? ? ? } else { ? ? ? ? ? ? for (int i = 0; i < size; i++) ? ? ? ? ? ? ? ? if (o.equals(elementData[i])) ? ? ? ? ? ? ? ? ? ? return i; ? ? ? ? } ? ? ? ? return -1; ? ? } ? ? public int lastIndexOf(Object o) { ? ? ? ? ?//分為o是否為空兩種情況 ? ? ? ? if (o == null) { ? ? ? ? ? ? //從后往前找 ? ? ? ? ? ? for (int i = size-1; i >= 0; i--) ? ? ? ? ? ? ? ? if (elementData[i]==null) ? ? ? ? ? ? ? ? ? ? return i; ? ? ? ? } else { ? ? ? ? ? ? for (int i = size-1; i >= 0; i--) ? ? ? ? ? ? ? ? if (o.equals(elementData[i])) ? ? ? ? ? ? ? ? ? ? return i; ? ? ? ? } ? ? ? ? return -1; ? ? }
從上面的源碼中我們可以看到:
- ArrayList 在初始化的時候如果我們沒有指定長度的話,它會有一個默認(rèn)長度10,每次擴(kuò)容的時候為增加1.5倍
- 然后是ArrayList 的一些常見的方法的源碼介紹
3.2Vector
Vector的底層也是通過數(shù)組實現(xiàn),方法與ArrayList基本一致,。但是Vector是線程安全的. 這是因為其加上了 synchronized 關(guān)鍵字, 用來保證線程安全。
- 優(yōu)點: 以數(shù)組的形式進(jìn)行存儲,因此隨機(jī)訪問速度較快,所有它適用于查詢;線程安全
- 缺點: 不適用于插入和刪除的操作 因為每次操作都需要移動數(shù)組中的元素
下面看下Vector的源碼:
? /** ? ? ?* Constructs an empty vector so that its internal data array ? ? ?* has size {@code 10} and its standard capacity increment is ? ? ?* zero. ? ? ?*/ ? ? public Vector() { ? ? ? ? this(10); //指定初始容量initialCapacity為10 ? ? } ? ? public Vector(int initialCapacity) { ? ? ? ? this(initialCapacity, 0);//指定capacityIncrement增量為0 ? ? } ? ? public Vector(int initialCapacity, int capacityIncrement增量為0) { ? ? ? ? super(); ? ? ? ? //判斷了形參初始容量initialCapacity的合法性 ? ? ? ? if (initialCapacity < 0) ? ? ? ? ? ? throw new IllegalArgumentException("Illegal Capacity: "+ ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?initialCapacity); ? ? ? ? //創(chuàng)建了一個Object[]類型的數(shù)組 ? ? ? ? this.elementData = new Object[initialCapacity];//默認(rèn)是10 ? ? ? ? //增量,默認(rèn)是0,如果是0,后面就按照2倍增加,如果不是0,后面就按照你指定的增量進(jìn)行增量 ? ? ? ? this.capacityIncrement = capacityIncrement; ? ? } ? ? //synchronized意味著線程安全的 ?? ?? ?public synchronized boolean add(E e) { ? ? ? ? modCount++; ? ? ?? ?//看是否需要擴(kuò)容 ? ? ? ? ensureCapacityHelper(elementCount + 1); ? ? ?? ?//把新的元素存入[elementCount],存入后,elementCount元素的個數(shù)增1 ? ? ? ? elementData[elementCount++] = e; ? ? ? ? return true; ? ? } ? ? private void ensureCapacityHelper(int minCapacity) { ? ? ? ? // overflow-conscious code ? ? ? ? //看是否超過了當(dāng)前數(shù)組的容量 ? ? ? ? if (minCapacity - elementData.length > 0) ? ? ? ? ? ? grow(minCapacity);//擴(kuò)容 ? ? } ? ? private void grow(int minCapacity) { ? ? ? ? // overflow-conscious code ? ? ? ? int oldCapacity = elementData.length;//獲取目前數(shù)組的長度 ? ? ? ? //如果capacityIncrement增量是0,新容量 = oldCapacity的2倍 ? ? ? ? //如果capacityIncrement增量是不是0,新容量 = oldCapacity + capacityIncrement增量; ? ? ? ? int newCapacity = oldCapacity + ((capacityIncrement > 0) ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?capacityIncrement : oldCapacity); ? ? ? ?? ? ? ? ? //如果按照上面計算的新容量還不夠,就按照你指定的需要的最小容量來擴(kuò)容minCapacity ? ? ? ? if (newCapacity - minCapacity < 0) ? ? ? ? ? ? newCapacity = minCapacity; ? ? ? ?? ? ? ? ? //如果新容量超過了最大數(shù)組限制,那么單獨處理 ? ? ? ? if (newCapacity - MAX_ARRAY_SIZE > 0) ? ? ? ? ? ? newCapacity = hugeCapacity(minCapacity); ? ? ? ?? ? ? ? ? //把舊數(shù)組中的數(shù)據(jù)復(fù)制到新數(shù)組中,新數(shù)組的長度為newCapacity ? ? ? ? elementData = Arrays.copyOf(elementData, newCapacity); ? ? } ? ? ?public boolean remove(Object o) { ? ? ? ? return removeElement(o); ? ? } ? ? public synchronized boolean removeElement(Object obj) { ? ? ? ? modCount++; ? ? ? ? //查找obj在當(dāng)前Vector中的下標(biāo) ? ? ? ? int i = indexOf(obj); ? ? ? ? //如果i>=0,說明存在,刪除[i]位置的元素 ? ? ? ? if (i >= 0) { ? ? ? ? ? ? removeElementAt(i); ? ? ? ? ? ? return true; ? ? ? ? } ? ? ? ? return false; ? ? } ? ? public int indexOf(Object o) { ? ? ? ? return indexOf(o, 0); ? ? } ? ? public synchronized int indexOf(Object o, int index) { ? ? ? ? if (o == null) {//要查找的元素是null值 ? ? ? ? ? ? for (int i = index ; i < elementCount ; i++) ? ? ? ? ? ? ? ? if (elementData[i]==null)//如果是null值,用==null判斷 ? ? ? ? ? ? ? ? ? ? return i; ? ? ? ? } else {//要查找的元素是非null值 ? ? ? ? ? ? for (int i = index ; i < elementCount ; i++) ? ? ? ? ? ? ? ? if (o.equals(elementData[i]))//如果是非null值,用equals判斷 ? ? ? ? ? ? ? ? ? ? return i; ? ? ? ? } ? ? ? ? return -1; ? ? } ? ? public synchronized void removeElementAt(int index) { ? ? ? ? modCount++; ? ? ? ? //判斷下標(biāo)的合法性 ? ? ? ? if (index >= elementCount) { ? ? ? ? ? ? throw new ArrayIndexOutOfBoundsException(index + " >= " + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?elementCount); ? ? ? ? } ? ? ? ? else if (index < 0) { ? ? ? ? ? ? throw new ArrayIndexOutOfBoundsException(index); ? ? ? ? } ? ? ? ?? ? ? ? ? //j是要移動的元素的個數(shù) ? ? ? ? int j = elementCount - index - 1; ? ? ? ? //如果需要移動元素,就調(diào)用System.arraycopy進(jìn)行移動 ? ? ? ? if (j > 0) { ? ? ? ? ? ? //把index+1位置以及后面的元素往前移動 ? ? ? ? ? ? //index+1的位置的元素移動到index位置,依次類推 ? ? ? ? ? ? //一共移動j個 ? ? ? ? ? ? System.arraycopy(elementData, index + 1, elementData, index, j); ? ? ? ? } ? ? ? ? //元素的總個數(shù)減少 ? ? ? ? elementCount--; ? ? ? ? //將elementData[elementCount]這個位置置空,用來添加新元素,位置的元素等著被GC回收 ? ? ? ? elementData[elementCount] = null; /* to let gc do its work */ ? ? }
從上面的源碼中我們可以看到:
Vector在初始化的時候如果我們沒有指定長度的話,它會有一個默認(rèn)長度10,每次擴(kuò)容的時候為增加2倍
然后是Vector
的一些常見的方法的源碼介紹
3.3LinkedList
LinkedList底層的數(shù)據(jù)存儲結(jié)構(gòu)是鏈表結(jié)構(gòu),而且還是一個雙向鏈表,可以實現(xiàn)雙向操作。此外,LinkedList還實現(xiàn)了棧和隊列的操作方法,因此也可以作為棧、隊列和雙端隊列來使用,如peek 、push、pop等方法。
- 優(yōu)點: 以鏈表形式進(jìn)行存儲,因此隨機(jī)訪問速度查詢慢,增刪快。
- 缺點: 線程不安全
下面看一下源碼:
int size = 0; Node<E> first;//記錄第一個結(jié)點的位置 Node<E> last;//記錄最后一個結(jié)點的位置 ? ? private static class Node<E> { ? ? ? ? E item;//元素數(shù)據(jù) ? ? ? ? Node<E> next;//下一個結(jié)點 ? ? ? ? Node<E> prev;//前一個結(jié)點 ? ? ? ? Node(Node<E> prev, E element, Node<E> next) { ? ? ? ? ? ? this.item = element; ? ? ? ? ? ? this.next = next; ? ? ? ? ? ? this.prev = prev; ? ? ? ? } ? ? } ? ? ? public boolean add(E e) { ? ? ? ? linkLast(e);//默認(rèn)把新元素鏈接到鏈表尾部 ? ? ? ? return true; ? ? } ? ? void linkLast(E e) { ? ? ? ? final Node<E> l = last;//用l 記錄原來的最后一個結(jié)點 ? ? ? ?? ? ? ? ? //創(chuàng)建新結(jié)點 ? ? ? ? final Node<E> newNode = new Node<>(l, e, null); ? ? ? ? //現(xiàn)在的新結(jié)點是最后一個結(jié)點了 ? ? ? ? last = newNode; ? ? ? ?? ? ? ? ? //如果l==null,說明原來的鏈表是空的 ? ? ? ? if (l == null) ? ? ? ? ? ? //那么新結(jié)點同時也是第一個結(jié)點 ? ? ? ? ? ? first = newNode; ? ? ? ? else ? ? ? ? ? ? //否則把新結(jié)點鏈接到原來的最后一個結(jié)點的next中 ? ? ? ? ? ? l.next = newNode; ? ? ? ? //元素個數(shù)增加 ? ? ? ? size++; ? ? ? ? //修改次數(shù)增加 ? ? ? ? modCount++; ? ? } ? ? ?public boolean remove(Object o) { ? ? ? ? //分o是否為空兩種情況 ? ? ? ? if (o == null) { ? ? ? ? ? ? //找到o對應(yīng)的結(jié)點x ? ? ? ? ? ? for (Node<E> x = first; x != null; x = x.next) { ? ? ? ? ? ? ? ? if (x.item == null) { ? ? ? ? ? ? ? ? ? ? unlink(x);//刪除x結(jié)點 ? ? ? ? ? ? ? ? ? ? return true; ? ? ? ? ? ? ? ? } ? ? ? ? ? ? } ? ? ? ? } else { ? ? ? ? ? ? //找到o對應(yīng)的結(jié)點x ? ? ? ? ? ? for (Node<E> x = first; x != null; x = x.next) { ? ? ? ? ? ? ? ? if (o.equals(x.item)) { ? ? ? ? ? ? ? ? ? ? unlink(x);//刪除x結(jié)點 ? ? ? ? ? ? ? ? ? ? return true; ? ? ? ? ? ? ? ? } ? ? ? ? ? ? } ? ? ? ? } ? ? ? ? return false; ? ? } ? ? E unlink(Node<E> x) {//x是要被刪除的結(jié)點 ? ? ? ? // assert x != null; ? ? ? ? final E element = x.item;//被刪除結(jié)點的數(shù)據(jù) ? ? ? ? final Node<E> next = x.next;//被刪除結(jié)點的下一個結(jié)點 ? ? ? ? final Node<E> prev = x.prev;//被刪除結(jié)點的上一個結(jié)點 ? ? ? ? //如果被刪除結(jié)點的前面沒有結(jié)點,說明被刪除結(jié)點是第一個結(jié)點 ? ? ? ? if (prev == null) { ? ? ? ? ? ? //那么被刪除結(jié)點的下一個結(jié)點變?yōu)榈谝粋€結(jié)點 ? ? ? ? ? ? first = next; ? ? ? ? } else {//被刪除結(jié)點不是第一個結(jié)點 ? ? ? ? ? ? //被刪除結(jié)點的上一個結(jié)點的next指向被刪除結(jié)點的下一個結(jié)點 ? ? ? ? ? ? prev.next = next; ? ? ? ? ? ? //斷開被刪除結(jié)點與上一個結(jié)點的鏈接 ? ? ? ? ? ? x.prev = null;//使得GC回收 ? ? ? ? } ? ? ? ? //如果被刪除結(jié)點的后面沒有結(jié)點,說明被刪除結(jié)點是最后一個結(jié)點 ? ? ? ? if (next == null) { ? ? ? ? ? ? //那么被刪除結(jié)點的上一個結(jié)點變?yōu)樽詈笠粋€結(jié)點 ? ? ? ? ? ? last = prev; ? ? ? ? } else {//被刪除結(jié)點不是最后一個結(jié)點 ? ? ? ? ? ? //被刪除結(jié)點的下一個結(jié)點的prev執(zhí)行被刪除結(jié)點的上一個結(jié)點 ? ? ? ? ? ? next.prev = prev; ? ? ? ? ? ? //斷開被刪除結(jié)點與下一個結(jié)點的連接 ? ? ? ? ? ? x.next = null;//使得GC回收 ? ? ? ? } ?? ??? ?//把被刪除結(jié)點的數(shù)據(jù)也置空,使得GC回收 ? ? ? ? x.item = null; ? ? ? ? //元素個數(shù)減少 ? ? ? ? size--; ? ? ? ? //修改次數(shù)增加 ? ? ? ? modCount++; ? ? ? ? //返回被刪除結(jié)點的數(shù)據(jù) ? ? ? ? return element; ? ? }
從上面的源碼中我們可以看到:
LinkedList
是基于鏈表的,所以沒有擴(kuò)容方法,默認(rèn)加入元素是尾部自動擴(kuò)容
然后是LinkedList的一些常見的方法的源碼介紹
3.4ArrayList與Vector的區(qū)別
它們的底層結(jié)構(gòu)都是數(shù)組,我們稱為動態(tài)數(shù)組。
- ArrayList是新版的動態(tài)數(shù)組,線程不安全,效率高,Vector是舊版的動態(tài)數(shù)組,線程安全,效率低。
- 動態(tài)數(shù)組的擴(kuò)容機(jī)制不同,ArrayList擴(kuò)容為原來的1.5倍,Vector擴(kuò)容增加為原來的2倍。
- 數(shù)組的初始化容量,如果在構(gòu)建ArrayList與Vector的集合對象時,沒有顯式指定初始化容量,那么Vector的內(nèi)部數(shù)組的初始容量默認(rèn)為10,而ArrayList在JDK1.6及之前的版本也是10,而JDK1.7之后的版本ArrayList初始化為長度為0的空數(shù)組,之后在添加第一個元素時,再創(chuàng)建長度為10的數(shù)組。
到此這篇關(guān)于學(xué)習(xí)Java中的List集合的文章就介紹到這了,更多相關(guān)Java中的List集合內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
jsp頁面中獲取servlet請求中的參數(shù)的辦法詳解
在JAVA WEB應(yīng)用中,如何獲取servlet請求中的參數(shù),本文講解了jsp頁面中獲取servlet請求中的參數(shù)的辦法2018-03-03java數(shù)學(xué)類Math?BigInteger?BigDecimal使用介紹
這篇文章主要為大家介紹了java數(shù)學(xué)類Math、BigInteger、BigDecimal的使用詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-06-06Maven的pom.xml中resources標(biāo)簽的用法
本文主要介紹了Maven的pom.xml中resources標(biāo)簽的用法,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2023-07-07Java 并發(fā)編程學(xué)習(xí)筆記之Synchronized簡介
雖然多線程編程極大地提高了效率,但是也會帶來一定的隱患。比如說兩個線程同時往一個數(shù)據(jù)庫表中插入不重復(fù)的數(shù)據(jù),就可能會導(dǎo)致數(shù)據(jù)庫中插入了相同的數(shù)據(jù)。今天我們就來一起討論下線程安全問題,以及Java中提供了什么機(jī)制來解決線程安全問題。2016-05-05Spring?Boot?MQTT?Too?many?publishes?in?progress錯誤的解決方
本文介紹Spring?Boot?MQTT?Too?many?publishes?in?progress錯誤的解決方案,文章圍繞主題展開詳細(xì)的內(nèi)容介紹,具有一定的參考價值,感興趣的小伙伴可以參考一下2022-07-07在java List中進(jìn)行模糊查詢的實現(xiàn)方法
下面小編就為大家?guī)硪黄趈ava List中進(jìn)行模糊查詢的實現(xiàn)方法。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2016-11-11