我们知道在java集合框架中有一个支持有序并且可以重复的List接口,而在此接口下有支持随机访问效率较高的ArrayList,底层是链表实现的LinkedList,和底层实现也是数组的Vector,今天我们就来看一个ArrayList的实现。
ArrayList的源码实现,或许大家也都或多或少的去看过,或者研究过。知道底层的实现依赖的是数组,初始长度是10。今天我们就仿照jdk中ArrayList的源码,自己去写一个ArrayList(所使用方法,变量的命名也全都仿照jdk的源码实现),目的就是为了更加的理解ArrayList。
package cn.bdqn.test;
public class ImplArrayList<T> {
/**
* 对象数组,保存元素
*/
private Object[] elementData;
/**
* 所包含元素的个数
*/
private int size;
/**
* 构造方法,创建容量为size的数组
*
* @param size
*/
public ImplArrayList(int size) {
this.elementData = new Object[size];
}
/**
* 默认构造方法,初始化数组容量为10
*/
public ImplArrayList() {
this(4);
}
/**
* 判断集合是否为空
*
* @return true:表示集合为空,false:表示集合非空
*/
public boolean isEmpty() {
return this.size == 0;
}
/**
* 得到集合中元素的个数
*
* @return 元素个数
*/
public int size() {
return this.size;
}
/**
* 添加元素
* @param e :待添加的元素
*/
public void add(T e) {
ensureCapacityInternal(this.size);
elementData[size++] = e;
}
/**
* 数据扩充
* @param size
*/
private void ensureCapacityInternal(int size) {
// 数组扩容
if (size == elementData.length) {
// 将当前数组赋给一个临时数组
Object[] temp = this.elementData;
// 重新声明一个新的数组
this.elementData = new Object[temp.length * 2];
for (int i = 0; i < temp.length; i++) {
this.elementData[i] = temp[i];
}
}
}
/**
* 根据索引添加元素
*
* @param i
* @param element
*/
public void add(int index, T element) {
//检查索引是否越界
rangeCheckForAdd(index);
//扩容
ensureCapacityInternal(this.size);
//元素后移
for (int i = this.size-1; i >=index; i--) {
this.elementData[i+1] = this.elementData[i];
}
this.elementData[index] = element;
this.size++;
}
/**
* 根据索引得到元素
* @param index
* @return
*/
public T get(int index){
rangeCheck(index);
return (T)this.elementData[index];
}
/**
* 判断索引是否越界
*
* @param index
* 索引位置
*/
private void rangeCheckForAdd(int index) {
if (index < 0 || index > this.size) {
throw new IndexOutOfBoundsException("数组越界异常:" + index);
}
}
/**
* 判断索引是否越界
* @param index
*/
private void rangeCheck(int index){
if(index>=this.size){
throw new IndexOutOfBoundsException("数组越界异常:" + index);
}
}
/**
* 根据索引删除元素
* @param index :待删除元素的索引
* @return :删除掉的元素
*/
public T remove(int index){
//检查元素是否越界
rangeCheck(index);
T oldValue = (T)this.elementData[index];
//移动的数量
int numMoved = this.size-index-1;
if(numMoved>0)
//数组copy
System.arraycopy(elementData, index+1, elementData,index,numMoved );
this.elementData[--size] = null;
return oldValue;
}
/**
* 修改指定索引位置的元素
* @param index
* @param element
* @return
*/
public T set(int index,T element){
rangeCheck(index);
T oldValue = (T)this.elementData[index];
this.elementData[index] = element;
return oldValue;
}
/**
* 根据元素值删除元素
* @param o :待删除的元素
* @return :是否删除成功
*/
public boolean remove(Object o){
if(o==null){
for (int index = 0; index < size; index++) {
if(this.elementData[index]==null){
//此处实现的删除与jdk的源码有些区别
//jdk是重新定义了一个fastRemove()方法进行调用的,
//此方法和remove()的区别是没有了索引越界的检查
//因为此时索引是不可能越界的(你也可以重新定义一个fastRemove()方法,进行调用)
remove(index);
return true;
}
}
}else{
for (int index = 0; index < size; index++) {
if(o.equals(this.elementData[index])){
remove(index);
return true;
}
}
}
return false;
}
}
测试在这里就不贴了,正如你使用ArrayList一样。