动态数组的Java实现思路:
底层用一个固定长度的数组element来保存数据,每插入一个元素之前先判断一下size+1是否大于底层数组element的长度,如果大于,那么将生成一个大于原来数组长度两倍的数组,然后将原有数据全部拷贝到扩容后的数组中。删除元素的时候也要将所有在删除元素后面的元素全部往前移。
具体实现:(有一些方法是和源码一样的)
import java.util.Arrays;
public class MyArrayList<E> {
//默认初始化长度为16
private final int DEFAULT_SIZE = 10;
//保存数组的长度
private int capacity;
//保存底层数组元素的个数
private int size = 0;
//用于存储数据的数组
private Object[] element;
/***
* 以默认数组长度初始化Object数组
*/
public MyArrayList(){
capacity = DEFAULT_SIZE;
element = new Object[DEFAULT_SIZE];
}
/***
* 以指定长度初始化Object数组
*/
public MyArrayList(int initSize) {
if(initSize>0) {
element = new Object[initSize];
}else if(initSize==0) {
element = new Object[0];
}
else {
throw new IllegalArgumentException("初始化数组长度异常: "+initSize);
}
}
/***
* @return 返回底层数组长度
*/
public int length(){
return size;
}
/***
* @return 如果底层数组长度为0返回true,否则返回false
*/
public boolean isEmpty() {
return size == 0;
}
/***
*
* @param 指定位置index的数据
* @return 返回指定位置的元素
*/
@SuppressWarnings("unchecked")
public <T> T get(int index){
if(index<0||index>size-1) {
throw new IndexOutOfBoundsException("数组下标越界...");
}
return (T)element[index];
}
/***
* 获取元素的下标
* @param obj
* @return 返回元素的下标
*/
public int indexOf(Object obj){
//为什么要区别判断null与非null,因为null不能使用equals判断,会抛出NullPointerException
if(obj==null){
for (int i = 0; i < size; i++)
if (element[i]==null)
return i;
}else {
for (int i = 0; i < size; i++)
if (obj.equals(element[i]))
return i;
}
return -1;
}
/***
* 向指定位置插入元素
* @param index 指定位置
* @param e 指定元素
*/
public void add(int index,E e){
if(index<0||index>size-1) {
throw new IndexOutOfBoundsException("数组下标越界...");
}
//判断数组是否到达最大容量
ensureCapacity(size+1);
//将index之后的所有元素向后移动一格
System.arraycopy(element, index, element, index + 1,size - index);
element[index] = e;
size++;
}
public void add(E e){
//判断数组是否到达最大容量
ensureCapacity(size+1);
element[size++] = e;
}
/***
* 扩充数组方法,如果当前数组已大最大容量则将数组容量扩充为原来的两倍
* @param minCapacity
*/
private void ensureCapacity(int minCapacity){
if(minCapacity>capacity){
while(minCapacity>capacity){
capacity <<=1;
}
element = Arrays.copyOf(element, capacity);
}
}
/***
* 删除指定下标元素
* @param index 指定下标
* @return oldValue 返回删除元素
*/
public E remove(int index){
if(index<0||index>size-1) {
throw new IndexOutOfBoundsException("数组下标越界...");
}
//保存一下要删除的元素
E oldValue = (E) element[index];
//计算删除该元素后需要往前移动的元素的个数
int numMoved = size - index - 1;
if (numMoved > 0)
System.arraycopy(element, index+1, element, index,numMoved);
element[--size] = null;
return oldValue;
}
/***
* 删除最后一个元素
* @return
*/
public E remove(){
return remove(size-1);
}
/***
* 清除element数组,并将size置零
*/
public void clear(){
Arrays.fill(element, null);
size = 0;
}
/***
* 循环遍历数组,返回数组所有元素的字符串表示
*/
public String toString(){
if(size==0) {
return "[]";
}
else {
StringBuffer sb = new StringBuffer("[");
for(int i = 0;i<size;i++){
sb.append(element[i].toString()+",");
}
int len = sb.length();
//在返回之前把最后多加进去的一个 , 号删除
return sb.delete(len-1, len).append("]").toString();
}
}
}
测试一下: