PS:若是以爲文章有什麼地方寫錯了,哪裏寫得很差,或者有什麼建議,歡迎指點。
數組是一種線性表數據結構。它用一塊連續的內存空間,來存儲相同類型的一組數據。java
顧名思義,線性表就是數據排列成像一條線同樣的結構。每一個線性表上的數據最多隻有前和後兩個方向,數組,鏈表,棧,隊列等都是典型的線性表結構。數組
與其相對立的,在非線性表中,數據之間並非簡單的先後關係,像樹,堆,圖等都是典型的非線性表。數據結構
即計算機分配連續的內存單元來存儲數據,相同類型的數據即每一個內存單元的大小是相同的。性能
如聲明一個長度爲 5 的 int 類型的數組 int[] arr = new int[5]
,計算機給數組分配了一塊連續的內存空間,其中內存塊的首地址爲 base_address = 0xc0000160e0,每一個內存單元佔 4 個字節:優化
數組的一個特色是能夠根據下標隨機訪問數組元素,其時間複雜度爲 O(1),那麼它是如何實現的呢?spa
計算機分配的內存單元存儲數據時,也會爲內存單元分配一個地址,而後能夠經過地址來訪問內存中的數據。由數組的內存空間連續的特性,當須要訪問某個元素時,它會經過下面的尋址公式來計算出該元素存儲的內存地址:code
// 一維數組 arr[n]: arr[i]_address = base_address + i * data_type_size // 二維數組 arr[m][n]: address = base_address + (i * n + j) * data_type_size
其中 data_type_size 表示數組中每一個元素的大小,如在 int 型的數組 arr 中,data_type_size 就爲 4 個字節。隊列
這樣,即可以很快的根據內存地址來讀取數據。圖片
在數組中,爲了保持內存數據的連續性,會致使插入、刪除這兩個操做比較低效。內存
例如在 插入操做 中,假設數組的長度爲 n,若咱們要在數組的第 k 個位置插入一個數據,爲了把第 k 個位置騰出來給新的數據,咱們須要將第 k ~ n 這部分的元素都順序地向後挪一位: arr[i] = arr[i-1]
。其時間複雜度爲 O(n)。
而在 刪除操做 中,若咱們要刪除數組的第 k 個元素,爲了內存的連續性,就須要將第 k ~ n 這部分的元素都順序地向前挪一位: arr[i] = arr[i+1]
。其時間複雜度爲 O(n)。
然而在不少咱們不須要考慮數組中元素的有序性,數組只被看成一個存儲數據的集合的時候,爲了不大規模的數據搬移,咱們能夠對插入和刪除操做作一些優化。例如:
這樣,其時間複雜度就會降爲 O(1) 。
對於數組類型,Java 中的 ArrayList 容器是基於數組實現的,那麼兩者相比各有什麼優勢和適用場景呢?
數組是根據固定容量建立的,在必要的時候咱們須要對數組 arr 進行擴容:
// 初始長度爲 10 int[] arr = new int[10]; for (int i = 0; i < arr.length; i++) { arr[i] = i+1; } ... // 下面決定須要對數組 arr 進行擴容 int[] newArr = new int[arr.length*2]; // 對原數組進行內容拷貝 for (int i = 0; i < arr.length; i++) { newArr[i] = arr[i]; } arr = newArr;
在對數組進行拷貝時除了利用 for 循環遍歷數組元素進行拷貝外,推薦使用更高效的 System.arraycopy() 方法。
System.arraycopy()
使用 native 關鍵字修飾,大大加快程序性能,爲 JVM 內部固有方法。它經過手工編寫彙編或其餘優化方法來進行 Java 數組拷貝,這種方式比起直接在 Java 上進行 for 循環或 clone 是更加高效的。數組越大致現地越明顯。
該方法用於從指定源數組中進行拷貝操做,能夠指定開始位置,拷貝指定長度的元素到指定目標數組中。其聲明以下:
public static native void arraycopy(Object src, int srcPos, Object dest, int destPos, int length);
參數說明:
例,數組 arr 進行擴容:
// 初始長度爲 10 int[] arr = new int[10]; for (int i = 0; i < arr.length; i++) { arr[i] = i+1; } ... // 下面決定須要對數組 arr 進行擴容 int[] newArr = new int[arr.length*2]; System.arraycopy(arr,0,newArr,0,10); // 對原數組進行內容拷貝 arr = newArr;
絕大部分數組和基於數組實現的容器(ArrayList 等)的擴容都是基於 System.arraycopy() 方法進行操做的。
歡迎您的點贊、收藏和評論!(完)