线性表(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)