CodeGym /Java Blog /Toto sisi /圖片中的ArrayList
John Squirrels
等級 41
San Francisco

圖片中的ArrayList

在 Toto sisi 群組發布
你好!今天的課程ArrayList將比以前的課程更容易也更難。
圖片中的 ArrayList - 1
這將更加困難,因為今天我們將深入了解ArrayList並研究各種操作期間發生的情況。另一方面,本課幾乎沒有代碼。主要是圖片和解釋。好吧,讓我們開始:) 如您所知,ArrayList內部有一個普通數組,用作數據存儲。在大多數情況下,我們不指定列表的確切大小。但是內部數組必須有一定的大小!確實如此。它的默認大小是 10

public static void main(String[] args) {
   ArrayList<Car> cars = new ArrayList<>();
}
圖片中的 ArrayList - 2 首先,讓我們看看添加新元素是什麼樣子的。第一項業務是檢查內部數組是否有足夠的空間在內部數組中以及是否可以容納更多元素。如果有空間,則將新元素添加到列表的末尾。當我們說“到最後”時,我們並不是指數組中的最後一個位置(那會很奇怪)。我們指的是最後一個當前元素之後的位置。它的索引將是cars.size()。我們的列表目前為空 ( cars.size() == 0)。因此,新元素將添加到位置 0。

ArrayList<Car> cars = new ArrayList<>();
Car ferrari = new Car("Ferrari 360 Spider");
cars.add(ferrari);
圖片中的 ArrayList - 3 這很清楚。如果我們插入中間,即在其他元素之間會發生什麼?

public static void main(String[] args) {
   ArrayList<Car> cars = new ArrayList<>();
   Car ferrari = new Car("Ferrari 360 Spider");
   Car bugatti = new Car("Bugatti Veyron");
   Car lambo = new Car("Lamborghini Diablo");
   Car ford = new Car("Ford Modneo");
  
   cars.add(ferrari);
   cars.add(bugatti);
   cars.add(lambo);
  
   cars.add(1, ford);// add ford to cell 1, which is already occupied
}
同樣,首先檢查數組中是否有足夠的空間。如果有足夠的空間,則元素向右移動,從我們插入新元素的位置開始。我們在位置 1 插入。換句話說,位置 3 的元素被複製到位置 4,元素 2 複製到位置 3,元素 1 複製到位置 2。 圖片中的 ArrayList - 4 然後我們的新元素被插入到它的位置。先前的元素 (bugatti) 已從那裡複製到新位置。 圖片中的 ArrayList - 5 現在讓我們看看如果沒有地方可以向數組中插入新元素,這個過程是如何發生的。 圖片中的 ArrayList - 6 當然,首先要檢查是否有足夠的空間。如果沒有足夠的空間,則在內部創建一個新數組ArrayList其大小是舊數組的大小乘以 1.5 加 1 在我們的例子中,新數組的大小將為 16。所有當前元素將被立即復製到那裡。 圖片中的 ArrayList - 7 舊數組將被垃圾收集器刪除,只有新的擴展數組會保留下來。現在有一個新元素的空間。我們將它插入位置 3,該位置已被佔用。現在熟悉的程序開始了。從索引 3 開始的所有元素都向右移動一位,然後新元素悄悄添加。 圖片中的 ArrayList - 8 插入完成!我們完成了插入。現在讓我們談談刪除項目。你會記得我們在處理數組時遇到了一個問題:刪除元素會在數組中產生“洞”。每次刪除,我們每次都必須編寫自己的代碼來執行此轉換。 ArrayList 遵循相同的原則,但它已經實現了這種機制。 圖片中的 ArrayList - 9 它看起來是這樣的: 圖片中的 ArrayList - 10 最後我們得到了我們想要的: 圖片中的 ArrayList - 11lambo元素已被刪除。這裡我們從中間移除了一個元素。顯然,從列表末尾刪除一個元素更快,因為該元素被簡單地刪除而不需要移動所有其他元素。讓我們再討論一下內部數組的維度以及它在內存中的排列方式。 擴展數組需要一些資源。 因此,不要創建ArrayList如果您確定它至少有 100 個元素,則使用默認大小。當您插入第 100 個元素時, 內部數組必須擴展6 倍,並且每次都必須移動所有元素。
  • 從 10 個元素到 16 個
  • 從 16 個元素到 25 個
  • 從 25 到 38
  • 從 38 到 58
  • 從 58 到 88
  • 從 88 到 133(即舊數組的大小乘以 1.5 加 1)
可以想像,這是相當耗費資源的。 因此,如果您已經知道(甚至大約)所需的項目數量,最好創建一個包含特定大小數組的列表:

ArrayList<Car> cars = new ArrayList<>(100);
現在,包含 100 個元素的數組的內存將一次性全部分配,從而使數組更有效率(不需要擴展)。這種策略也有不利的一面。 當您從 中刪除對象時ArrayList,內部數組的大小不會自動減小。 假設我們有一個ArrayList包含 88 個元素的完全完整的內部數組: 圖片中的 ArrayList - 12 在程序運行時,我們刪除了 77 個元素,因此只剩下 11 個: 圖片中的 ArrayList - 13 你已經猜到問題是什麼了嗎?你明白了,內存使用效率低下!我們在這裡只使用了 11 個位置,但我們已經為 88 個元素分配了內存。這比我們需要的多 8 倍!在這種情況下,我們可以使用該類的一種ArrayList特殊方法來優化我們的內存使用:trimToSize(). 此方法將內部數組的長度“修剪”為當前存儲在其中的元素數。 圖片中的 ArrayList - 14 現在我們只分配了我們需要的內存!:)
留言
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION