JavaRush /Java Blog /Random-TW /new ArrayList(????) 如何以及在哪裡初始化更好
Vovan
等級 22

new ArrayList(????) 如何以及在哪裡初始化更好

在 Random-TW 群組發布
不使用集合框架 來編寫程式碼將是瘋狂的。這是 Java 的一個精彩部分,有許多巧妙的解決方案。更重要的是,與陣列不同,您不必擔心大小。ArrayList會不斷成長,直到記憶體耗盡。開發人員不必擔心初始大小和ArrayIndexOutOfBoundsException錯誤。但如果有條件監控記憶體量怎麼辦?在處理集合時我們可以有效地使用記憶體嗎?
出現了一個標準問題:如何初始化列表?下面的程式碼將不起作用:它將導致編譯錯誤: 局部變數名稱可能尚未 初始化。Java 規格要求所有局部變數(存在於堆疊中的變數)都使用適當的值進行初始化。您可以這樣做:毫無疑問,清單必須被初始化。您可以在第一行建立列表,也可以做一些更聰明的事情並使用延遲 初始化,就像我們在 getAllNames()方法中所做的那樣。在這種情況下,清單只會在必要時建立 - 如果不滿足初始條件,清單將永遠不會出現在堆上。這裡我們來到了主要問題: 我們應該為列表設定什麼大小?最好的選擇是給他準確的尺寸。例如:在這種情況下,必須傳回 n 個名稱,因此會建立一個包含 n 個元素的集合。 然而, n的確切值並不總是已知。即使在給出的範例中,如果 n=1000並且只有 100 個可用名稱怎麼辦?使用集合時,最流行的方法是呼叫預設建構函式。如果您查看 Java 原始碼(版本 1.6),您會看到, 預設會建立一個包含 10 個元素的清單。也就是說,當我們不打算在清單中儲存超過 10 個元素時,我們可以安全地使用預設建構子。如果您嘗試新增第 11 個元素會發生什麼?好吧,沒什麼不好...元素將被成功添加。看方法: 陣列的大小是由 ensureCapacity方法控制的。 尺寸增加1.5倍。建立一個新數組並將元素移入其中。如果我們將大小設為 10,則在第 11 個元素上:
public List getAllNames() { List names; if (/*необходимые условия выполнены*/) { names = new ArrayList (); /*заполнение списка*/ } return names; }
List names = null; List names = new ArrayList (); List names = new ArrayList (0); List names = new ArrayList (size);
public List getTopNames (int n) { List names = null; if ( /*необходимые условия выполнены*/) { names = new ArrayList (n); /*заполнение списка*/ } return names; }
names = new ArrayList ();

/** * Конструирует пустой список с указанной начальной емкостью. * * @param initialCapacity начальная емкость списка * @exception IllegalArgumentException если указанная начальная емкость отрицательна * */ public ArrayList(int initialCapacity) { super(); if (initialCapacity < 0) this.elementData = new Object[initialCapacity]; } /** * Конструирует пустой список с начальной емкостью, равной 10. */ public ArrayList() { this(10); }
public Boolean add(E e) { ensureCapacity(size + 1); //увеличивает modCount!! elementData[size++] = e; return true; } public void ensureCapacity (int minCapacity) { modCount++; int oldCapacity = elementData.length; if (minCapacity > oldCapacity) { throw new IllegalArgumentException(“Illegal Capacity: ” + initialCapacity); Object oldData[] = elementData; int newCapacity = (oldCapacity * 3) / 2 + 1; if (newCapacity < minCapacity) newCapacity = minCapacity; // minCapacity обычно ближе к размеру, так что это беспроигрышно: elementData = Arrays.copyOf(elementData, newCapacity); } }
  • 大小改為 10 * 3 / 2 + 1 = 16
  • 下次增加 = 16 * 3 / 2 + 1 = 25
  • 下次增加 = 25 * 3 / 2 + 1 = 39 等等。
如果有 100 個元素, JVM將需要多次建立新陣列並將元素複製到其中。考慮到這一點,如果對所需的陣列大小有一個假設,最好將初始容量設定為接近該大小。以下是一些行動指南:
  1. 僅在需要時建立集合,否則將其初始化為 null 或使用Collections.EMPTY_LIST
  2. 如果您知道所需的確切大小,請在集合建構函式中指定它。
  3. 如果您確定元素數量不會超過 10,請隨意使用預設建構函數。
  4. 與創建零大小集合相關的風險是創建新數組和複製資料的頻率可能會更高。您需要非常仔細地考慮使用大小為零的集合是否有很多好處
  5. 如果你在方法開始時初始化的集合太大並且想要減少它,可以使用trimToSize()方法。
當然,這些準則適用於使用基於陣列的集合,而對於鍊錶來說,這些準則都沒有意義。事實上,這些問題不太可能成為程式的殺手,但如果有機會做得更好一點,為什麼不使用它呢。您還有其他有用的提示嗎?您是否找到了讓事情變得更好的方法?或者這一切都是不必要的嗎?你怎麼認為?
留言
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION