ArrayList
package com.sxxjun.tccdemo1;
import java.util.*;
public class ArrayListDemo<E> extends AbstractList<E> implements List<E> , RandomAccess,Cloneable,java.io.Serializable{
//容器初始化
private int DEFAULT_CAPACITY = 10;
// 空数组。当集合内容置空的时候,底层使用空数组标记
private Object [] EMPTY_ELEMENTDATA = {};
// 用于无参数构造方法
private final Object [] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};
// 保存ArrayList数据的数组,这个数组会不断的改变,
private Object [] elementData;
// ArrayList 所包含的元素个数,也就是在 ArrayList 集合底层,通过 size()方法,获取到的元素个数
private int size;
//序列化使用, 目前针对于当前的操作过程当中, 暂时不会使用得到。
private static final long serialVersionUID = 8683452581122892189L;
// 构造器
public ArrayListDemo(){
this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
}
@Override
public int size() {
return size;
}
@Override
public E get(int index) {
return elementData(index);
}
private E elementData(int index){
rangeCheck(index);
return (E)elementData[index];
}
/**
* check index
* @param index
*/
private void rangeCheck(int index) {
if (index >= size)
throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
}
private String outOfBoundsMsg(int index) {
return "Index: "+index+", Size: "+size;
}
/**
* 在构造方法当中,传递一个参数集合c,将集合 c 转换成为新的列表
* elementData 当中的数据,就是新集合存放的数据
* c.toArray 就是将原始集合的数据取出
* 如果取出的集合长度不为零的情况下,则复制 参数集合c 到 elementData 当中
* 如果取出的集合长度为零的情况下,则赋值为空数组 EMPTY_ELEMENTDATA
*/
public ArrayListDemo(Collection<? extends E> c){
elementData = c.toArray();
if ((size = elementData.length)!=0){
if (elementData.getClass() != Object [].class){
elementData = Arrays.copyOf(elementData, size ,Object [].class);
}
}else {
this.elementData = EMPTY_ELEMENTDATA;
}
}
/**
* 指定参数的长度大小
* 如果初始化的长度大于0,则返回新的数组
* 如果初始化的长度等于0,则返回默认的空数组作为集合 this.elementData = EMPTY_ELEMENTDATA;
* 如果初始化的长度小于0,则出现非法参数异常
*/
public ArrayListDemo(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);
}
}
// 1. Arrays.copyOf(elementData, newCapacity); 表示来自于 数组工具类 Arrays 当中的 copyOf() 底层使用的是 System.arraycopy() 方法
// 2. Math.max(DEFAULT_CAPACITY, minCapacity) 表示来自于 数学工具类 Math 当中的 max() 方法,比较两个数据最大值,取较大者,返回
// 扩容
/**
* 将指定的元素添加到此集合的末尾位置
*
* modCount 是来自于父类的 AbstractList 当中的成员变量
* add(e, elementData, size) 调用自己下面的重载方法
* return true 表示当前的方法,一定可以添加成功,因为List系列的集合添加数据都是允许成功的 true 如果是Set此方法返回false
*/
public boolean add(E e){
modCount++;
this.add(e, elementData, size);
return true;
}
/**
* 这个方法是私有方法,仅仅自己可以使用。不允许外界访问得到。便于上面的 add() 方法重载调用的
* 参数1: 表示需要添加的元素数据 E e
* 参数2: 表示成员变量当中, 需要维护管理的底层数组 Object[] elementData
* 参数3: 表示成员变量当中, size 容器 elementData 当中存放的真实有效的数据个数
* 方法里面的逻辑: 当size已经等于了内部容器 elementData 的最大长度,则准备进行扩容的操作,扩容使用 grow() 方法
* 无论上面是否进行了扩容的操作,这里都需要将添加的元素赋值到数组当中,也就是 elementData[s] = e;
* 并且将当前成员变量的 size 在原始数据的基础上面,增加1,表示添加了新的元素之后,长度变化了,增加了1
*/
private void add(E e,Object [] elementData ,int s){
if (s == elementData.length)
elementData = grow();
elementData[s] = e;
size = s + 1;
}
/**
* 这个方法是私有方法,仅仅自己可以使用。不允许外界访问得到。便于上面的 add() 方法调用的
* 方法的内部调用了 ArrayList 当中自己重载的方法 grow(size + 1) 同时传入了参数。
* 这里参数的含义,表示的是 集合当中总长度 size + 1 表示在原始size基础上增加1
* 方法的返回值是一个新的数组,也就是扩容之后的数组
*/
private Object[] grow() {
return grow(size + 1);
}
/**
* 这个方法是私有方法,仅仅自己可以使用。不允许外界访问得到。便于上面的 grow() 方法调用的
* 这里的参数 minCapacity ,就是上面传入的参数 size + 1,也就是说最小容量 minCapacity = size + 1
* 方法体当中的执行逻辑:
* 1. 获取到了底层维护数组的长度 int oldCapacity = elementData.length; 这里就是旧容量 oldCapacity
* 2. 判断旧容量 oldCapacity 是否小于0,也就是 else 的逻辑,
* 如果满足 if 当中的逻辑, 则表示 旧数组当中存在数据,并且 旧数组并不是 默认容量的空数组地址值
* 说明: 扩容过的就不会是之前默认 DEFAULTCAPACITY_EMPTY_ELEMENTDATA 的地址值
* 在这种情况下,就会得到 1.5被的数组长度整数,传递给 Arrays.copyOf()方法进行扩容,得到新数组返回
* 如果满足 else 当中的逻辑,则返回 DEFAULT_CAPACITY 和 minCapacity 较大值。
* 说明: DEFAULT_CAPACITY 值表示的是成员变量,默认为 10
* 说明: minCapacity 在低于10的时候,表示的会是扩容添加的长度1,2,3..9.10.11..
*/
private Object[] grow(int minCapacity) {
int oldCapacity = elementData.length;
if (oldCapacity > 0 || elementData != DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
// int newCapacity = ArraysSupport.newLength(oldCapacity,
// minCapacity - oldCapacity, /* minimum growth */
// oldCapacity >> 1 /* preferred growth */);
Double aDouble = oldCapacity * 1.5;
int newCapacity = Integer.parseInt(aDouble.toString());
return elementData = Arrays.copyOf(elementData, newCapacity);
} else {
return elementData = new Object[Math.max(DEFAULT_CAPACITY, minCapacity)];
}
}
public static void main(String[] args) {
ArrayListDemo<String> strings = new ArrayListDemo<>();
System.out.println(strings.size());
strings.add("a");
System.out.println(strings.get(0));
for (Object elementDatum : strings.elementData) {
System.out.println(elementDatum);
}
}
}