基本和ArrayList编写的没有太多差别,除了一些细节的地方,以供参考
/**
* 手写ArrayList
* 需要包含构造函数(有参和无参)、add(obj)、扩容机制
*/
public class MyArrayList implements Serializable {
//判断当前集合类是否被并发修改,即迭代器并发修改的fail-fast机制 就像版本号控制 如果之前保存的值和当前的值不一样返回异常
private transient int modCount = 0;
//第一次扩容的容量
private static final int DEFAULT_CAPCITY = 10;
//用于初始化空实例List
private static final Object[] EMPTY_ELEMENT_DATA = {};
//实际存储的元素 transient:避免序列化
transient Object[] elementDate;
//实际List集合大小 从0开始
private int size;
public MyArrayList(){
this.elementDate = EMPTY_ELEMENT_DATA;
}
public MyArrayList(int initialCapcity){
if(initialCapcity>0){
this.elementDate = new Object[initialCapcity];
}else if(initialCapcity == 0){
//初始化 防止空指针异常
this.elementDate = EMPTY_ELEMENT_DATA;
}else {
throw new IllegalArgumentException("参数异常");
}
}
/**
* 添加元素
*/
public boolean add(Object e){
//判断容量
ensureCapacityInternal(size+1);
//使用下标赋值 尾部插入
elementDate[size++] = e;
return true;
}
/**
* 计算容量+确保容量
* @param minCapacity
*/
private void ensureCapacityInternal(int minCapacity){
//用于并发判断
modCount++;
//如果是初次扩容,则使用默认容量
if(elementDate == EMPTY_ELEMENT_DATA){
minCapacity = Math.max(DEFAULT_CAPCITY,minCapacity);
}
//是否需要扩容,需要的最少容量大于现在数组的长度则要扩容
if(minCapacity - elementDate.length>0){
int oldCapactiy = elementDate.length;
int newCapacity = oldCapactiy + (oldCapactiy>>1);
//如果新容量小于最小容量 则将最小容量赋值给新的容量
if(newCapacity - minCapacity < 0){
newCapacity = minCapacity;
}
//创建新数组
Object [] objects = new Object[newCapacity];
//将旧的数据复制到新的数组里面
System.arraycopy(elementDate,0,objects,0,elementDate.length);
//修改引用
elementDate = objects;
}
}
/**
* 通过下标获取对象
* @return
*/
public Object get(int index){
//参数检查
rangeCheck(index);
return elementDate[index];
}
private void rangeCheck(int index){
if(index > size || size < 0 ){
throw new IndexOutOfBoundsException("数组越界");
}
}
/**
* 通过对象获取下标位置
* @param o
* @return
*/
public int indexOf(Object o){
if(o == null){
for (int i=0;i < size;i++){
if(elementDate[i]==null){
return i;
}
}
}else {
for (int i=0;i < size;i++){
if(o.equals(elementDate[i])){
return i;
}
}
}
return -1;
}
/**
* 更新下标元素
* @param index
* @param obj
* @return
*/
public Object set(int index,Object obj){
rangeCheck(index);
//拿去旧下标
Object oldValue = elementDate[index];
//替换
elementDate[index] = obj;
return oldValue;
}
/**
* 根据下标删除元素
* @return
*/
public Object remove(int index){
rangeCheck(index);
//用于并发判断
modCount++;
//获取旧元素
Object oldValue = elementDate[index];
//后面元素进行移动 计算删除位后面的元素个数
int numMoved = size - index - 1;
if (numMoved > 0){
//当前数组 从当前下标之后 拷贝到也就是覆盖当前数据 从当前下标
System.arraycopy(elementDate,index+1,elementDate,index,numMoved);
}
//最后一个元素进行置空 将多出的位置为空,没有应用对象 垃圾收集器就可以回收 如果不置空 就会保存应用
//可能造成内存泄漏
elementDate[--size] = null;
return oldValue;
}
/**
* 获取数组实际大小
* @return
*/
public int size(){
return this.size;
}
测试
public class Test {
public static void main(String [] args){
MyArrayList list = new MyArrayList();
//添加
for (int i = 0; i<10 ; i++){
list.add(i);
}
//遍历
for (int i = 0 ; i<list.size();i++){
System.out.println(list.get(i));
}
}
}