007Java集合003詳解Vector、Stack
阿新 • • 發佈:2021-09-28
本文主要學習了Vector和Stack,包括擴容機制和常用的屬性方法。
注意:本文基於JDK1.8進行記錄。
1 Vector
1.1 簡介
不常用的集合,和ArrayList類似,允許任何符合規則的元素插入,包括null和重複元素。
底層是陣列結構,提供了索引機制,查詢效率高,增刪效率低。
執行緒安全,使用了synchronized關鍵字。
1.2 擴容機制
擴容機制和ArrayList類似,初始容量預設為10,負載因子是1,表示當插入元素後個數超出原有長度時會進行擴增,擴容增量是預設為原容量,所以擴增後容量為2倍,可使用方法手動擴容和縮減。
最好指定初始容量值和增量,避免過多的進行擴容操作而浪費時間和效率。
1.3 方法說明
1.3.1 構造方法
1 // 空參構造器,返回預設容量為10的集合。2 public Vector(); 3 // 指定長度的構造器,預設增量為0。 4 public Vector(int initialCapacity); 5 // 指定長度和增量的構造器,預設增量為0。 6 public Vector(int initialCapacity, int capacityIncrement); 7 // 傳入了一個集合的構造器,如果集合長度為0,返回容量為0的集合。 8 public Vector(Collection<? extends E> c);
1.3.2 常用方法
1 // 獲取指定下標的元素。 2 public synchronized E get(intindex); 3 // 設定指定下標的指定元素,並返回舊元素。 4 public synchronized E set(int index, E element); 5 // 新增元素,並返回是否成功。 6 public synchronized boolean add(E e); 7 // 在指定位置新增指定元素。 8 public void add(int index, E element); 9 // 刪除指定位置的元素,並返回刪除的元素。 10 public synchronized E remove(int index); 11 // 刪除元素,並返回是否成功。 12 public booleanremove(Object o);
1.4 原始碼分析
1.4.1 屬性
1 // 陣列。 2 protected Object[] elementData; 3 // 元素個數。 4 protected int elementCount; 5 // 擴容增量 6 protected int capacityIncrement;
1.4.2 構造方法
1 // 空參構造器,返回預設容量為10的集合。 2 public Vector() { 3 this(10); 4 } 5 // 指定長度的構造器,預設增量為0。 6 public Vector(int initialCapacity) { 7 this(initialCapacity, 0); 8 } 9 // 指定長度和增量的構造器,預設增量為0。 10 public Vector(int initialCapacity, int capacityIncrement) { 11 super(); 12 if (initialCapacity < 0) 13 throw new IllegalArgumentException("Illegal Capacity: "+initialCapacity); 14 this.elementData = new Object[initialCapacity]; 15 this.capacityIncrement = capacityIncrement; 16 } 17 // 傳入了一個集合的構造器,如果集合長度為0,返回容量為0的集合。 18 public Vector(Collection<? extends E> c) { 19 elementData = c.toArray(); 20 elementCount = elementData.length; 21 // Object[]數組裡的型別不一定都是Object型別的,有可能是Object的子類,所以要判斷一下。 22 if (elementData.getClass() != Object[].class) 23 elementData = Arrays.copyOf(elementData, elementCount, Object[].class); 24 }
1.4.3 常用方法
1 // 獲取指定下標的元素。 2 public synchronized E get(int index) { 3 // 檢查指定下標是否越界。 4 if (index >= elementCount) 5 throw new ArrayIndexOutOfBoundsException(index); 6 // 返回指定下標的元素。 7 return elementData(index); 8 } 9 // 設定指定下標的指定元素,並返回舊元素。 10 public synchronized E set(int index, E element) { 11 // 檢查指定下標是否越界。 12 if (index >= elementCount) 13 throw new ArrayIndexOutOfBoundsException(index); 14 // 設定指定元素並返回舊元素。 15 E oldValue = elementData(index); 16 elementData[index] = element; 17 return oldValue; 18 } 19 // 新增元素,並返回是否成功。 20 public synchronized boolean add(E e) { 21 // 運算元自增。 22 modCount++; 23 // 擴容。 24 ensureCapacityHelper(elementCount + 1); 25 // 元素個數增加並設定指定元素。 26 elementData[elementCount++] = e; 27 // 返回成功。 28 return true; 29 } 30 // 在指定位置新增指定元素。 31 public void add(int index, E element) { 32 insertElementAt(element, index); 33 } 34 // 刪除指定位置的元素,並返回刪除的元素。 35 public synchronized E remove(int index) { 36 // 運算元自增。 37 modCount++; 38 // 檢查指定下標是否越界。 39 if (index >= elementCount) 40 throw new ArrayIndexOutOfBoundsException(index); 41 // 獲取指定下標的元素。 42 E oldValue = elementData(index); 43 // 需要移動的元素個數。 44 int numMoved = elementCount - index - 1; 45 if (numMoved > 0) 46 System.arraycopy(elementData, index+1, elementData, index, numMoved); 47 // 將最後一個元素設定為null並減少容量大小。 48 elementData[--elementCount] = null; 49 // 返回指定下標的元素。 50 return oldValue; 51 } 52 // 刪除元素,並返回是否成功。 53 public boolean remove(Object o) { 54 return removeElement(o); 55 }
1.4.4 擴容方法
1 // 對集合進行擴容。 2 public synchronized void ensureCapacity(int minCapacity) { 3 // 如果指定容量大於擴充值,則進行擴容。 4 if (minCapacity > 0) { 5 // 運算元自增。 6 modCount++; 7 ensureCapacityHelper(minCapacity); 8 } 9 } 10 // 對集合進行擴容。 11 private void ensureCapacityHelper(int minCapacity) { 12 // 如果最小值大於陣列長度,則進行擴容。 13 if (minCapacity - elementData.length > 0) 14 grow(minCapacity); 15 } 16 // 陣列作為一個物件,需要一定的記憶體儲存物件頭資訊,物件頭資訊最大佔用記憶體不可超過8位元組。 17 private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8; 18 // 擴容計算。 19 private void grow(int minCapacity) { 20 // 獲取原容量大小。 21 int oldCapacity = elementData.length; 22 // 如果增量大於0,則使用增量,否則使用原容量作為增量,最後加上原容量作為新容量。 23 int newCapacity = oldCapacity + ((capacityIncrement > 0) ? capacityIncrement : oldCapacity); 24 // 如果擴容後小於最小值,則設定容量為最小值。 25 if (newCapacity - minCapacity < 0) 26 newCapacity = minCapacity; 27 // 如果擴容後大於最大值,則進一步設定容量。 28 if (newCapacity - MAX_ARRAY_SIZE > 0) 29 newCapacity = hugeCapacity(minCapacity); 30 // 複製陣列。 31 elementData = Arrays.copyOf(elementData, newCapacity); 32 } 33 // 擴容後容量過大的處理方法。 34 private static int hugeCapacity(int minCapacity) { 35 // 如果最小值小於零,則表示溢位,丟擲記憶體溢位異常。 36 if (minCapacity < 0) 37 throw new OutOfMemoryError(); 38 // 如果擴容後的值大於最大值,則使用Integer的最大值,否則就使用最大值。 39 return (minCapacity > MAX_ARRAY_SIZE) ? Integer.MAX_VALUE : MAX_ARRAY_SIZE; 40 }
2 Stack
2.1 簡介
不常用的集合,繼承自Vector,允許任何符合規則的元素插入,包括null和重複元素。
同Vector類似,底層是陣列結構,但通過對Vector的擴充套件,將陣列結構倒置形成堆疊結構,使用典型的後進先出操作方式。
執行緒安全,使用了synchronized關鍵字。
2.2 擴容機制
同Vector。
2.3 方法說明
2.3.1 構造方法
1 public Stack();
2.3.2 常用方法
1 // 判斷是否為空。 2 public boolean empty(); 3 // 入棧,新增到棧頂。 4 public E push(E item); 5 // 出棧,檢視並刪除棧頂元素。 6 public synchronized E pop(); 7 // 檢視棧頂元素。 8 public synchronized E peek(); 9 // 查詢元素,返回棧中首次出現下標。 10 public synchronized int search(Object o);
2.4 原始碼分析
2.4.1 構造方法
1 public Stack() { 2 }
2.4.2 常用方法
1 // 判斷是否為空。 2 public boolean empty() { 3 // 通過Vector的size()方法判斷。 4 return size() == 0; 5 } 6 // 入棧,新增到棧頂。 7 public E push(E item) { 8 // 實際新增到陣列尾部。 9 addElement(item); 10 return item; 11 } 12 // 出棧,檢視並刪除棧頂元素。 13 public synchronized E pop() { 14 E obj; 15 int len = size(); 16 // 實際檢視陣列尾部元素。 17 obj = peek(); 18 // 實際刪除陣列尾部元素。 19 removeElementAt(len - 1); 20 return obj; 21 } 22 // 檢視棧頂元素。 23 public synchronized E peek() { 24 int len = size(); 25 if (len == 0) 26 throw new EmptyStackException(); 27 // 實際檢視陣列尾部元素。 28 return elementAt(len - 1); 29 } 30 // 查詢元素,返回棧中首次出現下標。 31 public synchronized int search(Object o) { 32 // 實際檢視元素在陣列最後出現位置。 33 int i = lastIndexOf(o); 34 if (i >= 0) { 35 // 轉換為棧中位置。 36 return size() - i; 37 } 38 return -1; 39 }