數組對應的英文是array,是一個存儲相同類型的變量所組成的一個有序集合,數組中每個變量稱爲元素,每一個元素都有一個對應的索引(索引從0開始)。
數組的存儲方式以下:
數組還有另外一個特色,就是在內存中是順序存儲的。
內存是由一個個連續的內存單元所組成的,每個內存單元都對應一個地址,在內存單元中,有些被佔用了,有些是空閒的。
數組中的每個元素,都存儲在內存單元中,而且這些內存單元之間緊密排列,既不能打亂存儲順序,也不能跳過某個內存單元進行存儲。數組
一、讀取元素
對於數組來講,讀取元素是最簡單的操做。因爲數組在內存中順序存儲,因此只要給出一個數組的索引,就能夠讀取到索引對應的元素。app
二、修改元素
更新數組中的某一個元素,也是一個很是簡單的操做。直接利用數組的索引,就能夠把新值賦值給索引對應的元素。ide
三、插入元素
在數組中插入元素分爲三種狀況:函數
這是最簡單的狀況,直接把插入的元素放在數組的尾部空閒的位置就能夠了。ui
稍微複雜一些,在數組中每個元素都對應一個索引,因此首先先把插入位置的元素和後面的元素向後移動,再把插入的元素插入到對應的索引中。this
假如如今有一個長度爲10的數組,而且這個數組中已經填滿了元素,若是這時還想添加一個元素,該怎麼辦?
這裏就涉及到了擴容機制了,在一開始數組的長度就已經肯定了,那麼如何擴容呢?
咱們能夠建立一個新的數組,而且這個新數組的長度是原來的數組的長度的2倍,而後再把舊數組當中的元素插入到新數組當中,這樣就實現了數組的擴容。code
四、刪除元素
刪除元素和插入元素的過程正好相反,咱們把要刪除的元素後面的元素往前移動就能夠了。注意:雖然這裏不涉及擴容問題,可是若是當前的數組的元素的個數要比數組的長度小不少,是否是就浪費了內存?因此咱們能夠在這裏加入縮容機制,防止浪費內存。orm
總體代碼以下:blog
/** * 描述:基於數組二次封裝成動態數組。 * <p> * Create By ZhangBiao * 2020/5/8 */ public class Array<E> { private E[] data; private int size; /** * 構造函數,傳入數組的容量capacity構造Array。 * * @param capacity 容量大小 */ public Array(int capacity) { data = (E[]) new Object[capacity]; size = 0; } /** * 無參數的構造函數,默認數組的容量capacity=10。 */ public Array() { this(10); } public Array(E[] arr) { this.data = (E[]) new Object[arr.length]; for (int i = 0; i < arr.length; i++) { this.data[i] = arr[i]; } this.size = this.data.length; } /** * 獲取數組的容量。 * * @return */ public int getCapacity() { return data.length; } /** * 獲取數組中的元素個數。 * * @return */ public int getSize() { return size; } /** * 返回數組是否爲空。 * * @return */ public boolean isEmpty() { return size == 0; } /** * 向全部元素後添加一個新元素 * * @param e */ public void addLast(E e) { /*if (size == data.length) { throw new IllegalArgumentException("AddLast failed. Array is full."); } data[size] = e; size++;*/ add(size, e); } public void addFirst(E e) { add(0, e); } /** * 在index索引的位置插入一個新元素e * * @param index * @param e */ public void add(int index, E e) { if (index < 0 || index > size) { throw new IllegalArgumentException("Add failed. Require index >= 0 and index <= size."); } if (size == data.length) { resize(2 * data.length); } for (int i = size - 1; i >= index; i--) { data[i + 1] = data[i]; } data[index] = e; size++; } /** * 擴容 * * @param newCapacity */ private void resize(int newCapacity) { E[] newData = (E[]) new Object[newCapacity]; for (int i = 0; i < size; i++) { newData[i] = data[i]; } data = newData; } /** * 獲取index索引位置的元素。 * * @param index * @return */ public E get(int index) { if (index < 0 || index >= size) { throw new IllegalArgumentException("Get failed. Index is illgal."); } return data[index]; } /** * 獲取索引爲0的元素。 * * @return */ public E getFirst() { return get(0); } /** * 獲取索引爲size-1的元素。 * * @return */ public E getLast() { return get(size - 1); } /** * 修改index索引位置的元素爲e。 * * @param index * @param e */ public void set(int index, E e) { if (index < 0 || index >= size) { throw new IllegalArgumentException("Set failed. Index is illegal."); } data[index] = e; } /** * 查找數組中是否有元素e。 * * @param e * @return */ public boolean contains(E e) { for (int i = 0; i < size; i++) { if (data[i] == e) { return true; } } return false; } /** * 查找數組中元素e所在的索引,若是不存在元素e,則返回-1。 * * @param e * @return */ public int find(E e) { for (int i = 0; i < size; i++) { if (data[i] == e) { return i; } } return -1; } /** * 從數組中刪除index位置的元素,返回刪除的元素。 * * @param index * @return */ public E remove(int index) { if (index < 0 || index >= size) { throw new IllegalArgumentException("Remove failed. Index is illegal."); } E ret = data[index]; for (int i = index + 1; i < size; i++) { data[i - 1] = data[i]; } size--; if (size == data.length / 4 && data.length / 2 != 0) { resize(data.length / 2); } return ret; } /** * 從數組中刪除第一個元素並返回刪除的元素。 * * @return */ public E removeFirst() { return remove(0); } /** * 從數組中刪除最後一個元素並返回刪除的元素。 * * @return */ public E removeLast() { return remove(size - 1); } /** * 從數組中刪除元素e。 * * @param e */ public void removeElement(E e) { int index = find(e); if (index != -1) { remove(index); } } public void swap(int i, int j) { if (i < 0 || i >= size || j < 0 || j >= size) { throw new IllegalArgumentException("Index is Illegal"); } E temp = data[i]; data[i] = data[j]; data[j] = temp; } @Override public String toString() { StringBuilder res = new StringBuilder(); res.append(String.format("Array: size = %d , capacity = %d\n", size, data.length)); res.append('['); for (int i = 0; i < size; i++) { res.append(data[i]); if (i != size - 1) { res.append(", "); } } res.append(']'); return res.toString(); } }
一、優點
數組擁有高效的隨機訪問能力,只要給出索引,就能夠當即找到對應的元素。
二、劣勢
數組的劣勢體如今插入元素和刪除元素,因爲數組的存儲方式,致使在插入和刪除這兩個操做中大量的元素須要被迫移動,從而影響效率。索引