首先在分析源码前,先了解下几点
1. jdk 1.7之后 数组默认数据大小代码存放在 add方法中 (jdk 1.6默认构造函数初始化elementData大小)
2.arrayList 底层采用数组实现的 数组名称为 elementData
-----ArrayList分析源码开始---
这里的ensureCapacityInternal() size参数默认没赋值
我们来看一下这个方法干什么用的
在这里可以看到 DEFAULT_CAPACITY 默认数组长度定义为10,最小数组为1 ,将最大数组长度进行比较然后将值比较后的值返回出去
modCount++:主要是用来记录修改次数
然后看到grow方法的主要作用是将 当前minCapacity的长度 赋值给 elementData数组长度
在上面的步骤中已经知道了elementData已经被默认赋值长度为10了
elementData[size++] = e; 这个就是将数据存储到数组 size长度下标中
看完源码分析之后,就来简单的手写一下ArrayList集合
/**
* 手写自定义ArrayList集合
* @author 作者:旷黎明
* @date 2019.6.18
*/
public class ExtArrayList {
/**
* ArrayList底层采用数组存放
*/
private Object[] elementData;
/**
* 默认数组容量
*/
private static final int DEFAULT_CAPACITY = 10;
/**
* 定义一个空数组
*/
private static final Object[] EMPTY_ELEMENTDATA = {};
/**
* 记录ArrayList下标长度
*/
private int size;
/**
* 指定ArrayList 底层数组初始的容器长度
* @param initialCapacity
*/
public ExtArrayList(int initialCapacity) {
if (initialCapacity > 0) {
this.elementData = new Object[initialCapacity];
} else if (initialCapacity == 0) {
this.elementData = EMPTY_ELEMENTDATA;
} else {
throw new IllegalArgumentException("Illegal Capacity: " +
initialCapacity);
}
}
/**
* 默认初始化容量为10
* 注意:这里笔者这样写是以1.6的方式写的,1.7是在add方法中初始化容量的
*/
public ExtArrayList(){
this(DEFAULT_CAPACITY);
}
public boolean add(Object object){
ensureCapacityInternal(size + 1);
//使用下标进行赋值
elementData[size++] = object;
return true;
}
/**
* 以下标插入数据
* @param index
* @param object
* @return
*/
public boolean add(int index,Object object){
ensureCapacityInternal(size + 1);
/**
* 在index下标后面的值 移动到 index + 1 下标上 所以 index下标的值就是无用的值
*
* 值 1 2 3 4 5
* 下标 0 1 2 O 3 4
*/
System.arraycopy(elementData,index,elementData,index+1,size - index);
//将object值 覆盖到 index下标中
elementData[index] = object;
//容器数据+1
size++;
return true;
}
/**
* 通过下标获取值
* @param index
* @return
*/
public Object get(int index){
rangeCheck(index);
return elementData[index];
}
/**
* 判断下标是否越界
* @param index
*/
private void rangeCheck(int index) {
if (index >= size){
throw new IndexOutOfBoundsException("下标越界!!!");
}
}
/**
* 判断数组最小容量是否大于初始容量 大于则扩容
* @param minCapacity
*/
private void ensureCapacityInternal(int minCapacity) {
// overflow-conscious code
if (minCapacity - elementData.length > 0)
grow(minCapacity);
}
/**
* 数组扩容
* @param minCapacity
*/
private void grow(int minCapacity) {
//源数组长度
int oldCapacity = elementData.length;
//新数组长度
int newCapacity = oldCapacity + (oldCapacity >> 1);
/**
* 如果集合初始长度设置为1,但是需要添加3个元素,那么这个时候在第2个元素就得开始进行扩容
* 这个时候上面的新数组长度以1.5倍进行扩容(但是java里面是int所以为1)
* 新数组长度为 1 - 最小容量长度为 2 就无法进行扩容
* 所以这里的判断就是就是将最小数组容量长度赋值给新数组长度
* 调试一下 一目了然
*/
if (newCapacity - minCapacity < 0)
newCapacity = minCapacity;
// if (newCapacity - MAX_ARRAY_SIZE > 0)
//// newCapacity = hugeCapacity(minCapacity);
//将新数组长度 copy到 源数组长度中 并且将值也copy至其中了
elementData = Arrays.copyOf(elementData, newCapacity);
}
/**
* 返回数组长度
* @return
*/
public int getSize(){
return size;
}
/**
* 删除下标
* 删除原理:
* @param index
* @return
*/
public Object remove(int index){
//1.判断下标是否越界
rangeCheck(index);
//2.计算删除元素后的长度
int numMoved = size - index - 1;
if(numMoved > 0){
//将删除元素下标后面的值覆盖到当前下标值上
System.arraycopy(elementData,index + 1 ,elementData,index,numMoved);
}
//将最后数组的值置空
elementData[--size] = null;
return index;
}
/**
* 以对象进行删除
* @param o
* @return
*/
public boolean remove(Object o){
if(o != null){
for(int i = 0; i < elementData.length; i++){
if(o.equals(elementData[i])){
remove(i);
return true;
}
}
}
return false;
}
}
最后来进行测试一波
public class TestList {
public static void main(String[] args) {
/**
* 添加数据
*/
ExtArrayList extArrayList = new ExtArrayList(1);
extArrayList.add("测试1");
extArrayList.add("测试2");
extArrayList.add("测试3");
extArrayList.add("测试4");
extArrayList.add("测试5");
/**
* 遍历数据
*/
for(int i = 0; i< extArrayList.getSize();i++){
System.out.println(extArrayList.get(i));
}
/**
* 删除后,查看遍历的数据
*/
{
System.out.println("<------------ 以下标删除后 ---------->");
extArrayList.remove(1);
/**
* 遍历数据
*/
for(int i = 0; i< extArrayList.getSize();i++){
System.out.println(extArrayList.get(i));
}
}
}
}
但是有没有发现现在这个集合没有使用泛型,所以我们现在就把泛型也添加上来
public interface ExtList<E> {
public boolean add(E e);
public boolean add(int index,E e);
public E get(int index);
public E remove(int index);
public boolean remove(E e);
public int getSize();
}
/**
* 手写自定义ArrayList集合
* @author 作者:旷黎明
* @date 2019.6.18
*/
public class ExtArrayList<E> implements ExtList<E>{
//这里把上面的方法全部实现过来 即可,我这里偷个懒只实现了一个方法
/**
* 添加数据
* @param e
* @return
*/
@Override
public boolean add(E e){
ensureCapacityInternal(size + 1);
//使用下标进行赋值
elementData[size++] = e;
return true;
}
}
最后在进行测试,成功