線性表(List):零個或多個數據元素的有限序列。數組
關鍵字有兩個:性能
「零個」也就是說線性表是能夠爲空的;spa
「有限序列」無論多長的線性表,總要有一個最大長度,而且元素與元素之間是一對一的關係,也即有必定的順序。code
在Java中有一個很「神奇的」類,就是ArrayList。它神奇的地方在於它使用起來和數組同樣簡單,但卻提供了更多更方便的方法。感受上ArrayList是能夠無限添加元素的!這一點太方便了,它是怎麼作到的呢?blog
其實,ArrayList是底層就是用數組來實現的!可是上次不是才說數組的長度是不能變的嗎?實際上,它能夠實現「無限的」添加元素只是由於它的底層有一個機制,在數組空元素用完的時候會生成一個長度更長的數組,而後把以前的元素複製過去,這樣就實現了擴容。但對於使用者來講,咱們不須要關心這些細節。這就是Java基礎類帶來的方便啊!ci
咱們本身來實現一個ArrayList,不過擴容的功能麻煩了點就不作了~~~但基本的一個線性表應該具備的功能應該是(假定要放入的元素都是int型的,固然改爲範型也是能夠的):rem
增:boolean add(int value)在表的末尾添加新元素;boolean insert(int index, int value)。get
刪:boolean remove(int index)移除指定位置的元素;void clear()清空整個表。it
改:boolean update(int index, int value)將指定位置的元素修改爲指定的值。class
查: int select(int value)在線性表中查詢指定的值,返回元素的位置。若是不存放,返回「-1」。
還有一些功能也是必須的:
長度:int size()返回線性表的長度。
判空:boolean isEmpty()返回該線性表是否爲空。
取值:int getValue(int index)獲取特定位置的值。
好的,如今咱們開始寫代碼:
首先固然是想一下怎樣初始化的問題了。
本質上,咱們仍是經過數組來實現,因此咱們應該是先定義一個必定長度的的數組,而且,咱們應該用一個變量來記錄咱們添加了多少個元素吧。咱們把這個類叫MyArrayList:
public class MyArrayList { // 這個線性表的最大長度 public static final int MAX_LEN = 100; // 用來保存數據的數組 private int[] array = new int[MAX_LEN]; // 用定記錄線性表的長度 private int len; }
好的,下面就是重頭戲了,咱們來實現功能了,先從add開始。
思路以下:
先判斷線性表的長度是否等於最大的長度,若是相等,就說明表已滿。不能插入返回false;不然,插入到末尾處,表的長度加1,返回true。代碼實現以下:
public boolean add(int value) { // 判斷線性表是否已滿 if (len == MAX_LEN) { return false; } else { array[len] = value; len++; return true; } }
在指定的位置插入數據比較麻煩一點。想象一下,你在飯堂打飯,有前面有一我的插隊。那應該是最後的人先退後一步吧,這樣前面的人,每一個都退後一個就可以騰出位置。因此在指定位置插入的話,要先作這樣一步工做。
同理,刪除一個元素的話,那也就是把這個元素以後的數據依次往前移到一位咯~~~
其餘方法也是差很少這個樣,就不說了,本身看代碼快點~~~
public class MyArrayList { // 這個線性表的最大長度 public static final int MAX_LEN = 100; // 用來保存數據的數組 private int[] array = new int[MAX_LEN]; // 用定記錄線性表的長度 private int len; /** * 添加數據到線性表末尾 * @param value 要添加的值 * @return 添加成功爲true,添加失敗爲false */ public boolean add(int value) { // 判斷線性表是否已滿 if (len == MAX_LEN) { return false; } else { array[len] = value; len++; return true; } } /** * 在指定的位置添加數據 * @param index 添加的位置 * @param value 添加的數據 * @return 添加成功爲true,添加失敗爲false */ public boolean insert(int index, int value) { if (len == MAX_LEN) { return false; } // 若是插入的位置不合理 if (index < 0 || index > len) { return false; } else { // 在index以後的元素都應該向後移 for (int i = len; i > index; i--) { array[i] = array[i - 1]; } array[index] = value; len++; return true; } } /** * 清空線性表 */ public void clear() { len = 0; } /** * 移除指定位置的元素 * @param index 要移除的元素的位置 * @return 移除成功爲true,添加失敗爲false */ public boolean remove(int index) { if (index < 0 || index > len - 1) { return false; } else { // 至關於把index後面的元素向前移一位 for (int i = index; i < len - 1; i++) { array[i] = array[i + 1]; } len--; return true; } } /** * 更新指定位置的元素的值 * @param index 要更新的元素的位置 * @param value 新的值 * @return 更新成功爲true,添加失敗爲false */ public boolean update(int index, int value) { if (index < 0 || index > len - 1) { return false; } else { array[index] = value; return true; } } /** * 查詢指定的數值是否在線性表中 * @param value 要查詢的數值 * @return 若是找到的話爲第一個匹配的位置,找不到的話,返回-1 */ public int select(int value) { int index = 0; for (; index < len; index++) { if (array[index] == value) { break; } } if (index == len) { return -1; } else { return index; } } /** * 得到線性表的長度 * @return 線性表的長度 */ public int size() { return len; } /** * 判斷線性表是否爲空 * @return 若是爲空,返回true,不然爲false */ public boolean isEmpty() { if (len == 0) { return true; } else { return false; } } /** * 獲取某一位置的值 * @param index 指定的元素位置 * @return 該位置的值,若是指定的位置不合理,拋出異常 */ public int getValue(int index) { if (index < 0 || index > len - 1) { // 咱們這裏就不本身定義異常了,讓系統去拋出~~~ return array[MAX_LEN]; } else { return array[index]; } } }
其實這樣下來,Java自帶的ArrayList可以實現的功能咱們已經實現了大半了~~~,從上面的代碼不難看出,若是在ArrayList進行大量的數據插入和刪除操做,效率是比較低的。但它的讀取性能是至關高的。
總的來講,ArrayList主要有兩個缺點:
第一是插入和刪除操做帶來的大量的數據移動。好比每次都往第0個位置插入或刪除,當數據元素不少時,這樣的操做也是很費時的。
第二是,默認數組分配的大小問題。默認的數組分配得小,那麼一會兒就不夠用了,就要進行數組的「擴容」;若是分配得過大的話,那麼就極可能浪費大量的空間。因此,若是咱們在事前已經大概知道有多少個元素時,最好是使用ArrayList的:public ArrayList(int initialCapacity)這個構造方法。(默認的數組長度是10)