ArrayList的底层无非就是其众多的使用方法及很重要的扩容机制:
封装的方法有:add\get\set\indexOf\remove\size
扩容机制:
jdk1.7之前初始默认为10,
jdk1.8之后初始默认为0,实际值长度大于0小于10时,扩容为10;实际长度大于10时,则扩容大小为实际长度+实际长度右移2的一次方(实际长度/2)
package com.yjkf.zh.arrayList;
import java.io.Serializable;
/**
* 包含构造1函数(有参,无参)、add()、扩容机制
*/
public class MyArrayList implements Serializable {
//使用这个字段,来判断当前集合是否被并发修改,即迭代器并发修改的fail-fast机制
private transient int modCount = 0;
//第一次扩容的容量
private static final int DEFAULT_CAPACITY = 10;
//用于初始化空的List
private static final Object[] EMPTY_ELEMENT_DATA = {};
//实际存储的元素,transient代表不能被序列化
transient Object[] elementData;
//实际List集合大小,可以从0开始
private int size;
//无参构造
public MyArrayList(){
this.elementData = EMPTY_ELEMENT_DATA;
}
//有参构造
public MyArrayList(int initislCapcity){
if(initislCapcity>0){
this.elementData = new Object[initislCapcity];
}else if(initislCapcity == 0){
this.elementData = EMPTY_ELEMENT_DATA;
}else{
throw new IllegalArgumentException("参数异常");
}
}
public boolean add(Object e){
//判断容量
ensureCapacityInternal(size+1);
//使用下标赋值,尾部插入
elementData[size++] = e;
return true;
}
//计算容量+确保容量
private void ensureCapacityInternal(int minCapacity){
//用于并发判断
modCount++;
//如果是初次扩容,则使用默认的容量
if(elementData == EMPTY_ELEMENT_DATA){
minCapacity = Math.max(DEFAULT_CAPACITY,minCapacity);
}
//是否需要扩容,需要的最少容量大于现在数组的长度则要扩容
if(minCapacity - elementData.length >0){
int oldCapacity = elementData.length;
int newCapacity = oldCapacity + (oldCapacity>>1);
//如果新容量<最小容量,则将最新的容量到给新的容量
if(newCapacity - minCapacity <0){
newCapacity = minCapacity;
}
//创建新数组
Object[] objects = new Object[newCapacity];
//将旧的数据复制到新的数组里面
System.arraycopy(elementData,0,objects,0,elementData.length);
//修改引用
elementData = objects;
}
}
/**
* 通过下标获取对象
* @param index
* @return
*/
public Object get(int index){
rangeCheck(index);
return elementData[index];
}
private void rangeCheck(int index){
if(index>size || size<0){
throw new IndexOutOfBoundsException("数据越界了");
}
}
/**
* 判断对象所在的位置
* @return
*/
public int indexOf(Object o){
if(o==null){
for(int i =0;i<size;i++){
if(elementData[i]==null){
return i;
}
}
}else {
for (int i=0;i<size;i++){
if(o.equals(elementData[i])){
return i;
}
}
}
return -1;
}
public Object set(int index,Object obj){
rangeCheck(index);
Object oldValue = elementData[index];
elementData[index] = obj;
return oldValue;
}
/**
* 根据索引删除元素
* @param index
* @return
*/
public Object remove(int index){
rangeCheck(index);
//用于并发判断
modCount++;
Object oldValue = elementData[index];
//计算要删除的位置后面有几个元素
int numMoved = size - index -1;
if(numMoved>0){//拷贝哪一个,从哪里开始,拷贝到哪去,从哪里开始,拷贝多少个
System.arraycopy(elementData,index+1,elementData,index,numMoved);
}
//将多出的位置置为空,没有引用对象,垃圾收集器可以回收,如果不为空,将会保存一个引用,可能会造成内存泄漏
elementData[--size]=null;
return oldValue;
}
//获取数组实际大小
public int size(){
return this.size;
}
}