我的原則:先會用再說,內部慢慢來。
學以致用,根據場景學源碼
文章目錄
- 一、架構
- 二、 RandomAccess 接口子類
- 三、 AbstractSequentialList 抽象類子類
- 四、ArrayList 類
- 4.1 變量
- 4.2 方法
- 4.2.1 初始化(3個)
- 3.2.2 get 與 set 方法
- 4.2.3 add 方法
- 4.2.4 ensureCapacityInternal 方法
- 4.2.5 calculateCapacity 方法
- 4.2.6 ensureExplicitCapacity 方法
- 4.2.7 grow 方法
- 4.2.8 remove 方法
- 4.2.9 removeAll 方法
- 4.2.10 batchRemove 方法(private)
- 4.2.11 retainAll 方法
- 4.2.12 trimToSize 方法
- 4.2.13 fastRemove 方法 (private)
- 4.2.14 clear 方法
- 4.2.15 subList 方法
- 4.2.16 writeObject 方法
- 4.2.17 readObject 方法
- 4.2.18 爲什麼elementData是transient的?
- 4.3 是否指定 capacity 帶來的區別
- 五、Vector 類
- 六、CopyOnWriteArrayList 類
- 七、ImmutableList 類
- 八、LinkedList 類
- 九、番外篇
一、架構
1.1 常見子類 UML
1.2 簡述
二、 RandomAccess 接口子類
2.1 ArrayList 類
2.2 Vector 類
2.3 CopyOnWriteArrayList 類
2.4 ImmutableList 類
三、 AbstractSequentialList 抽象類子類
3.1 LinkedList 類
四、ArrayList 類
- java.util.ArrayList
public class ArrayList<E> extends AbstractList<E>
implements List<E>, RandomAccess, Cloneable, java.io.Serializable
- 注意:實現了 RandomAccess,表明是支持隨機訪問,那麼也就是內部是數組Array 結構。
4.1 變量
變量名 | 備註 |
---|---|
private static final int DEFAULT_CAPACITY = 10 | 內部Array數組默認長度,不夠再擴容。 |
private static final Object[] EMPTY_ELEMENTDATA = {} | 空數組。(標誌性的)構造方法、trimToSize 、readObject用到 |
private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {}; | 確定容量用的。我們將此與EMPTY_ELEMENTDATA區分開來,以瞭解在添加第一個元素時要膨脹多少。ensureCapacity、calculateCapacity 用到 |
transient Object[] elementData | 元素數組 |
private int size | 數組長度 |
4.2 方法
4.2.1 初始化(3個)
- 默認構造方法
public ArrayList() {
this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
}
- 帶initialCapacity構造方法
public ArrayList(int initialCapacity) {
if (initialCapacity > 0) {
this.elementData = new Object[initialCapacity];
} else if (initialCapacity == 0) {
this.elementData = EMPTY_ELEMENTDATA;
} else {
throw new IllegalArgumentException("Illegal Capacity: "+
initialCapacity);
}
}
- 帶 Collection 的構造方法
public ArrayList(Collection<? extends E> c) {
elementData = c.toArray();
if ((size = elementData.length) != 0) {
// c.toArray might (incorrectly) not return Object[] (see 6260652)
if (elementData.getClass() != Object[].class)
elementData = Arrays.copyOf(elementData, size, Object[].class);
} else {
// replace with empty array.
this.elementData = EMPTY_ELEMENTDATA;
}
}
- 三構造方法,注意一下 DEFAULTCAPACITY_EMPTY_ELEMENTDATA 與 EMPTY_ELEMENTDATA 的區別,前面那個是默認的。
3.2.2 get 與 set 方法
public E get(int index) {
rangeCheck(index);
return elementData(index);
}
public E set(int index, E element) {
rangeCheck(index);
E oldValue = elementData(index);
elementData[index] = element;
return oldValue;
}
都是先檢查下標是否溢出,然後再進行 get 或者 set。
4.2.3 add 方法
- java.util.ArrayList#add(E)
public boolean add(E e) {
ensureCapacityInternal(size + 1); // Increments modCount!!
elementData[size++] = e;
return true;
}
- 先檢查數組內部容量 ensureCapacityInternal
- 設置元素
4.2.4 ensureCapacityInternal 方法
- java.util.ArrayList#ensureCapacityInternal
private void ensureCapacityInternal(int minCapacity) {
ensureExplicitCapacity(calculateCapacity(elementData, minCapacity));
}
- calculateCapacity 先計算所需要數組容量
- ensureExplicitCapacity 確保容量充足,必要時候擴容
- 上層調用:
=== 點擊查看top目錄 ===
4.2.5 calculateCapacity 方法
- java.util.ArrayList#calculateCapacity (計算所需要數組容量 )
private static int calculateCapacity(Object[] elementData, int minCapacity) {
// 若是默認的,也即是調用了
if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
return Math.max(DEFAULT_CAPACITY, minCapacity);
}
return minCapacity;
}
- ArrayList默認構造方法下,會進行擴容到合適的容量。
- 返回最少需要的容量
- 上層調用:
- ensureCapacityInternal 確保合適容量
- readObject 從輸入流轉換成 List 會用到
4.2.6 ensureExplicitCapacity 方法
- java.util.ArrayList#ensureExplicitCapacity
private void ensureExplicitCapacity(int minCapacity) {
modCount++;
// overflow-conscious code
if (minCapacity - elementData.length > 0)
grow(minCapacity);
}
- modCount++ ,那麼加入你在Iterator遍歷,那麼你就會拋出 ConcurrentModificationException
- 判斷是否能夠裝下新元素,不夠的話就 grow
4.2.7 grow 方法
- java.util.ArrayList#grow
- 容量增長方法,內部是調用 native 方法進行復制。
private void grow(int minCapacity) {
// overflow-conscious code
int oldCapacity = elementData.length;
int newCapacity = oldCapacity + (oldCapacity >> 1);
if (newCapacity - minCapacity < 0)
newCapacity = minCapacity;
if (newCapacity - MAX_ARRAY_SIZE > 0)
newCapacity = hugeCapacity(minCapacity);
// minCapacity is usually close to size, so this is a win:
//
elementData = Arrays.copyOf(elementData, newCapacity);
}
- 此處應該注意,如果每次添加一個元素都要進行擴容的話,那麼及其浪費性能。
4.2.8 remove 方法
方法名 | 備註 |
---|---|
public E remove(int index) | 按 index 刪除 |
public boolean remove(Object o) | 按 Object 刪除 |
public boolean removeIf(Predicate<? super E> filter) | 按條件刪除 |
protected void removeRange(int fromIndex, int toIndex) | 刪除一定範圍內的元素 |
public boolean removeAll(Collection<?> c) | 批量刪除 |
- java.util.ArrayList#remove(int) 刪除 index 下標的元素
public E remove(int index) {
rangeCheck(index);
modCount++;
E oldValue = elementData(index);
int numMoved = size - index - 1;
if (numMoved > 0)
System.arraycopy(elementData, index+1, elementData, index,
numMoved);
elementData[--size] = null; // clear to let GC do its work
return oldValue;
}
內部原理:
- 拿到老的 Element ,待會返回
- 使用 native 底層的複製方法,把 index+1 以及後面的元素全部複製到index的位置來。
- 最後一個元素設置爲null
- size - 1
- java.util.ArrayList#remove(java.lang.Object) 刪除某個元素
public boolean remove(Object o) {
if (o == null) {
for (int index = 0; index < size; index++)
if (elementData[index] == null) {
fastRemove(index);
return true;
}
} else {
for (int index = 0; index < size; index++)
if (o.equals(elementData[index])) {
fastRemove(index);
return true;
}
}
return false;
}
內部原理:
- 拿到老的 Element
- 使用 native 底層的複製方法,把 index+1 以及後面的元素全部複製到index的位置來。fastRemove方法
- 最後一個元素設置爲null
- size - 1
- return true / false
- 注意一下:若有100w個數據,你從頭刪到尾巴,那麼肯定非常耗時。因爲每次都要進行復制。
4.2.9 removeAll 方法
- java.util.ArrayList#removeAll
- 把Collection中包含c集合中的元素都移除掉(求差集)
public boolean removeAll(Collection<?> c) {
Objects.requireNonNull(c);
return batchRemove(c, false);
}
4.2.10 batchRemove 方法(private)
- java.util.ArrayList#batchRemove
private boolean batchRemove(Collection<?> c, boolean complement) {
final Object[] elementData = this.elementData;
int r = 0, w = 0;
boolean modified = false;
try {
for (; r < size; r++)
if (c.contains(elementData[r]) == complement)
elementData[w++] = elementData[r];
} finally {
// Preserve behavioral compatibility with AbstractCollection,
// even if c.contains() throws.
// r != size 的情況: c.contains() 丟出 Exception,(看下 java.util.AbstractCollection#contains )
if (r != size) {
// 如果丟出異常,那麼把後面沒處理的都給銜接上放在原 elementData 上面
System.arraycopy(elementData, r,
elementData, w,
size - r);
w += size - r;
}
// retainAll 情況下:如果 w == size ,那麼說明原來的Collection 與要處理的 Collection 一模一樣
// removeAll 情況下:如果 w == size ,那麼一個沒刪除
// 那麼 w!= size 是什麼情況呢?就是上面for處理後,w 後面還有元素,後面的元素都不要了,需要設置爲 null,協助 gc
if (w != size) {
// clear to let GC do its work
for (int i = w; i < size; i++)
elementData[i] = null;
modCount += size - w;
size = w;
modified = true;
}
}
return modified;
}
- 看下上層引用
- retainAll 與 removeAll
for (; r < size; r++)
if (c.contains(elementData[r]) == complement)
elementData[w++] = elementData[r];
---
retainAll:
elementData : A B C D F G
c : A C E
size = 10
elementData : A C
---
removeAll:
elementData : A B C D F G
c : A C E
size = 10
elementData : B D F G
4.2.11 retainAll 方法
- java.util.ArrayList#retainAll 方法
- 把Collection中不是c的元素移除掉(求合集)
public boolean retainAll(Collection<?> c) {
Objects.requireNonNull(c);
return batchRemove(c, true);
}
4.2.12 trimToSize 方法
- java.util.ArrayList#trimToSize 方法
- 壓縮容量,假如內存1w的數組裏面只有1000個元素,調用這個方法就是把這1000個元素copy到另外一個新的數組,指針指向這個新的數組。
public void trimToSize() {
modCount++;
if (size < elementData.length) {
elementData = (size == 0)
? EMPTY_ELEMENTDATA
: Arrays.copyOf(elementData, size);
}
}
4.2.13 fastRemove 方法 (private)
- java.util.ArrayList#fastRemove 方法
private void fastRemove(int index) {
modCount++;
int numMoved = size - index - 1;
if (numMoved > 0)
System.arraycopy(elementData, index+1, elementData, index,
numMoved);
elementData[--size] = null; // clear to let GC do its work
}
4.2.14 clear 方法
- java.util.ArrayList#clear 方法
public void clear() {
modCount++;
// clear to let GC do its work
for (int i = 0; i < size; i++)
elementData[i] = null;
size = 0;
}
- 數組內元素指針全部指向null,協助GC
- size 設置爲 0
- 思考下,爲什麼不直接 elementData = null
我自己的看法:如果你不想用這個list了,那麼直接 list = null,如果你還想用,那麼就調用 clear,免得你待會還得再 new 一個。
4.2.15 subList 方法
- java.util.ArrayList#subList 方法
- 淺複製,得到子List,實際上操作的還是父本身的list內部元素,詳情看內部類 subList 實現
public List<E> subList(int fromIndex, int toIndex) {
subListRangeCheck(fromIndex, toIndex, size);
return new SubList(this, 0, fromIndex, toIndex);
}
static void subListRangeCheck(int fromIndex, int toIndex, int size) {
if (fromIndex < 0)
throw new IndexOutOfBoundsException("fromIndex = " + fromIndex);
if (toIndex > size)
throw new IndexOutOfBoundsException("toIndex = " + toIndex);
if (fromIndex > toIndex)
throw new IllegalArgumentException("fromIndex(" + fromIndex +
") > toIndex(" + toIndex + ")");
}
4.2.16 writeObject 方法
- java.util.ArrayList#writeObject 方法
- 將 Collection 寫入輸出流 ObjectOutputStream
private void writeObject(java.io.ObjectOutputStream s)
throws java.io.IOException{
// Write out element count, and any hidden stuff
int expectedModCount = modCount;
s.defaultWriteObject();
// Write out size as capacity for behavioural compatibility with clone()
s.writeInt(size);
// Write out all elements in the proper order.
for (int i=0; i<size; i++) {
s.writeObject(elementData[i]);
}
if (modCount != expectedModCount) {
throw new ConcurrentModificationException();
}
}
4.2.17 readObject 方法
- java.util.ArrayList#readObject 方法
- 將輸入流 ObjectInputStream 寫入Collection
private void readObject(java.io.ObjectInputStream s)
throws java.io.IOException, ClassNotFoundException {
elementData = EMPTY_ELEMENTDATA;
// Read in size, and any hidden stuff
s.defaultReadObject();
// Read in capacity
s.readInt(); // ignored
if (size > 0) {
// be like clone(), allocate array based upon size not capacity
int capacity = calculateCapacity(elementData, size);
SharedSecrets.getJavaOISAccess().checkArray(s, Object[].class, capacity);
ensureCapacityInternal(size);
Object[] a = elementData;
// Read in all elements in the proper order.
for (int i=0; i<size; i++) {
a[i] = s.readObject();
}
}
}
4.2.18 爲什麼elementData是transient的?
- ArrayList在序列化的時候會調用writeObject,直接將size和element寫入ObjectOutputStream;反序列化時調用readObject,從ObjectInputStream獲取size和element,再恢復到elementData。
- 爲什麼不直接用elementData來序列化,而採用上訴的方式來實現序列化呢?原因在於elementData是一個緩存數組,它通常會預留一些容量,等容量不足時再擴充容量,那麼有些空間可能就沒有實際存儲元素,採用上訴的方式來實現序列化時,就可以保證只序列化實際存儲的那些元素,而不是整個數組,從而節省空間和時間。
4.2.19 toArray 方法
- java.util.ArrayList#toArray() 方法
public Object[] toArray() {
return Arrays.copyOf(elementData, size);
}
- java.util.Arrays#copyOf(T[], int) 方法
public static <T> T[] copyOf(T[] original, int newLength) {
return (T[]) copyOf(original, newLength, original.getClass());
}
- java.util.Arrays#copyOf(U[], int, java.lang.Class<? extends T[]>) 方法
public static <T,U> T[] copyOf(U[] original, int newLength, Class<? extends T[]> newType) {
@SuppressWarnings("unchecked")
T[] copy = ((Object)newType == (Object)Object[].class)
? (T[]) new Object[newLength]
: (T[]) Array.newInstance(newType.getComponentType(), newLength);
System.arraycopy(original, 0, copy, 0,
Math.min(original.length, newLength));
return copy;
}
- java.lang.System#arraycopy
- 底層是深複製
public static native void arraycopy(Object src, int srcPos,
Object dest, int destPos,
int length);
- List內部也是數組Array,複製的底層就是調用 System#arraycopy 將List內部數組複製成一個新的Object數組
=== 點擊查看top目錄 ===
4.2.20 size 方法
- java.util.ArrayList#size 方法
public int size() {
return size;
}
4.3 是否指定 capacity 帶來的區別
private static void test01() {
ArrayList<String> stringList = new ArrayList<>(100000000); // 162ms
ArrayList<String> stringList = new ArrayList<>(1); // 9000ms
long begin = System.currentTimeMillis();
for (int i = 0; i < 100000000; i++) {
stringList.add("A");
}
long end = System.currentTimeMillis();
System.out.println("ArrayList -> " + (end - begin));
}
- 162ms VS 9000m ,原因就是內部的 copy 操作,每次擴容都會全量複製一次。
五、Vector 類
public class Vector<E>
extends AbstractList<E>
implements List<E>, RandomAccess, Cloneable, java.io.Serializable
- 在 ArrayList 基礎上,所有方法加上 synchronized 。
六、CopyOnWriteArrayList 類
- 實現 RandomAccess 的常用子類
- 該類,寫的時候加鎖,然後全copy,用於寫少讀多的場合。讀的時候不加鎖。
6.1 變量
變量 | 備註 |
---|---|
final transient ReentrantLock lock = new ReentrantLock(); | 寫的時候加鎖 |
private transient volatile Object[] array; | 數組,存放元素,transient說明重寫了 readObject 與 writeObject 方法,目的是爲了不存儲空數據 |
6.2 代碼
- 整體代碼:
package java.util.concurrent;
public class CopyOnWriteArrayList<E>
implements List<E>, RandomAccess, Cloneable, java.io.Serializable {
/** The lock protecting all mutators */
final transient ReentrantLock lock = new ReentrantLock();
/** The array, accessed only via getArray/setArray. */
private transient volatile Object[] array;
...
}
- 查詢方法相比 ArrayList 無任何改動。
- 寫入方法:
6.2.1 set 方法
- java.util.concurrent.CopyOnWriteArrayList#set 方法
public E set(int index, E element) {
final ReentrantLock lock = this.lock;
lock.lock();
try {
Object[] elements = getArray();
E oldValue = get(elements, index);
if (oldValue != element) {
int len = elements.length;
Object[] newElements = Arrays.copyOf(elements, len);
newElements[index] = element;
setArray(newElements);
} else {
// Not quite a no-op; ensures volatile write semantics
setArray(elements);
}
return oldValue;
} finally {
lock.unlock();
}
}
- 注意
- 寫的時候,先上 lock
- Arrays.copyOf 內部使用 native 方法進行復制
- 替換掉老數組
- 釋放 lock
七、ImmutableList 類
- 該類內的全部元素,一初始化便註定不能改變。
- 元素不可改變的方法,任何一個寫操作都會拋出 UnsupportedOperationException .
- 拋出異常的方法
方法 | 描述 |
---|---|
add(E e) | throw new UnsupportedOperationException() |
remove(Object object) | throw new UnsupportedOperationException(); |
addAll(Collection<? extends E> newElements) | throw new UnsupportedOperationException(); |
removeAll(Collection<?> oldElements) | throw new UnsupportedOperationException(); |
retainAll(Collection<?> elementsToKeep) | throw new UnsupportedOperationException(); |
clear() | throw new UnsupportedOperationException(); |
package com.google.common.collect;
@GwtCompatible(serializable = true, emulated = true)
@SuppressWarnings("serial") // we're overriding default serialization
public abstract class ImmutableList<E> extends ImmutableCollection<E>
implements List<E>, RandomAccess {
}
7.1 構造方法 ImmutableList
ImmutableList() {}
- default 類型的構造方法,說明只供同一個 package 下的使用,真正的初始化方法是 of
7.2 初始化方法 of
@SuppressWarnings("unchecked")
public static <E> ImmutableList<E> of() { return (ImmutableList<E>) EMPTY; }
public static <E> ImmutableList<E> of(E element) { return new SingletonImmutableList<E>(element); }
public static <E> ImmutableList<E> of(E e1, E e2) { return construct(e1, e2); }
public static <E> ImmutableList<E> of(E e1, E e2, E e3) { return construct(e1, e2, e3); }
public static <E> ImmutableList<E> of(E e1, E e2, E e3, E e4) { return construct(e1, e2, e3, e4); }
public static <E> ImmutableList<E> of(E e1, E e2, E e3, E e4, E e5) { return construct(e1, e2, e3, e4, e5);}
public static <E> ImmutableList<E> of(E e1, E e2, E e3, E e4, E e5, E e6) {return construct(e1, e2, e3, e4, e5, e6);}
public static <E> ImmutableList<E> of(E e1, E e2, E e3, E e4, E e5, E e6, E e7) {return construct(e1, e2, e3, e4, e5, e6, e7);}
public static <E> ImmutableList<E> of(E e1, E e2, E e3, E e4, E e5, E e6, E e7, E e8) { return construct(e1, e2, e3, e4, e5, e6, e7, e8);}
public static <E> ImmutableList<E> of(E e1, E e2, E e3, E e4, E e5, E e6, E e7, E e8, E e9) {return construct(e1, e2, e3, e4, e5, e6, e7, e8, e9);}
public static <E> ImmutableList<E> of(E e1, E e2, E e3, E e4, E e5, E e6, E e7, E e8, E e9, E e10) {return construct(e1, e2, e3, e4, e5, e6, e7, e8, e9, e10);}
public static <E> ImmutableList<E> of(E e1, E e2, E e3, E e4, E e5, E e6, E e7, E e8, E e9, E e10, E e11) {return construct(e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11);}
public static <E> ImmutableList<E> of( E e1, E e2, E e3, E e4, E e5, E e6, E e7, E e8, E e9, E e10, E e11, E e12, E... others) {
Object[] array = new Object[12 + others.length];
array[0] = e1;
array[1] = e2;
array[2] = e3;
array[3] = e4;
array[4] = e5;
array[5] = e6;
array[6] = e7;
array[7] = e8;
array[8] = e9;
array[9] = e10;
array[10] = e11;
array[11] = e12;
System.arraycopy(others, 0, array, 12, others.length);
return construct(array);
}
- 我還是沒搞懂爲什麼要寫那麼多個 of 方法,直接下面這樣不行嗎???
public static <E> ImmutableList<E> of( E e1,E... others) {
Object[] array = new Object[1 + others.length];
array[0] = e1;
System.arraycopy(others, 0, array, 1, others.length);
return construct(array);
}
7.3 construct 方法
private static <E> ImmutableList<E> construct(Object... elements) {
return asImmutableList(checkElementsNotNull(elements));
}
- private 與 static 表明是一個靜態私有構造方法,也就是該方法不會被外部調用。
7.4 checkElementsNotNull 方法
- 該方法確保存入的元素 Element 不能爲 null
- ArrayList 、LinkedList 、Vector 允許null元素
static Object[] checkElementsNotNull(Object... array) {
return checkElementsNotNull(array, array.length);
}
static Object[] checkElementsNotNull(Object[] array, int length) {
for (int i = 0; i < length; i++) {
checkElementNotNull(array[i], i);
}
return array;
}
// We do this instead of Preconditions.checkNotNull to save boxing and array
// creation cost.
static Object checkElementNotNull(Object element, int index) {
if (element == null) {
throw new NullPointerException("at index " + index);
}
return element;
}
- 雖然不能寫,但是也就不能完全實現線程安全,畢竟 sort 方法還不是安全的。
八、LinkedList 類
public class LinkedList<E>
extends AbstractSequentialList<E>
implements List<E>, Deque<E>, Cloneable, java.io.Serializable
{
- 注意:這個類就不實現 RandomAccess 隨機存儲結構,而是
8.1 變量
變量名 | 備註 |
---|---|
transient Node last; | 元素數組 |
transient Node first; | 元素數組 |
transient int size = 0 | 數組長度 |
- 注意:變量都是 transient
8.2 方法 (public)
8.2.1 插入 add
方法名 | 備註 |
---|---|
public boolean add(E e) | 往最後面插入 |
public void add(int index, E element) | 在某個 index 後插入 element |
public void addFirst(E e) | 往最前面插入 |
public void addLast(E e) | 往最後面插入 |
public boolean addAll(Collection<? extends E> c) | 插入某個Collection |
public boolean addAll(int index, Collection<? extends E> c) | 在固定 index 後面插入某個Collection |
public boolean offer(E e) | 往最後面插入 |
public boolean offerFirst(E e) | 往最前面插入 |
public boolean offerLast(E e) | 往最後面插入 |
public void push(E e) | 往最前面插入addFirst(e); |
- add = offer 插最後 ,push 插開頭
8.2.2 刪除 remove
方法名 | 備註 |
---|---|
public E removeFirst() | 摘掉第一個 |
public E removeLast() | 摘掉最後一個 |
public E remove(int index) | 移除掉某個 index 下的element |
public boolean remove(Object o) | 移除掉某個元素 |
public E remove() | 拉出第一個元素(要remove,遇 null 拋Exception) |
public boolean removeFirstOccurrence(Object o) | remove(o); |
public boolean removeLastOccurrence(Object o) | 從後往前面刪 |
public E poll() | 拉出第一個元素(要remove,遇 null 返回 null) |
public E pollFirst() | 拉出第一個元素(要remove,遇 null 返回 null) |
public E pollLast() | 拉出最後一個元素(要remove,遇 null 返回 null) |
public E pop() | pop出第一個元素(要remove,遇 null 拋Exception) removeFirst(); |
- remove = pop 遇 null 拋出 Exception
- poll 遇 null 返回 null
8.2.3 設置 set
方法名 | 備註 |
---|---|
public E set(int index, E element) | 設置 index 下面的 Element |
8.2.4 get 查詢
方法名 | 備註 |
---|---|
public E get(int index) | 獲取某個 index 下的 Element |
public E getFirst() | 拿到第一個Element |
public E getLast() | 拿到最後一個 Element |
public E element() | 拿到第一個元素 (不remove,遇 null 拋Exception) |
public E peek() | 拿到第一個元素(不remove,遇 null 返回 null) |
public E peekFirst() | 拿到第一個元素(不remove,遇 null 返回 null) |
public E peekLast() | 拿到最後一個元素(不remove,遇 null 返回 null) |
8.2.5 其他操作
方法名 | 備註 |
---|---|
public int indexOf(Object o) | 查找某個元素存在的下標,找不到返回 -1 |
public int lastIndexOf(Object o) | 查找某個元素存在的下標(從後面開始找),找不到返回 -1 |
public boolean contains(Object o) | 是否包含某個 Element |
public int size() | collection 長度 |
public void clear() | 清除元素 |
public ListIterator listIterator(int index) | 拿到 ListItr |
public Iterator descendingIterator() | 拿到從後往前的 Iterator |
public Object clone() | 克隆,淺複製 shallow copy |
public Object[] toArray() | 轉成數組 |
public Spliterator spliterator() | 拿到從前往後的 Iterator |