package com.sanmubird.basicDataStructure;
import java.util.Arrays;
public class ArrayList implements List {
/** ArrayList 是一个类,一个类就会有对象,属性,构造方法,方法
* ArrayList 是基于数组来实现List接口; 那么它的元素就会有 存储在数组中的元素, 和ArrayList的长度
* 这个地方需要区分size= ArrayList.size() 和 length = Array.length ;
* size 是 已经占用的长度;
* length 是数组的长度; length 》= size 当,size > length 时,数组要动态扩容;
* */
// 数组默认的长度
private static final int DEFAULT_SIZE = 10;
// ArrayList的大小
private int size ;
// 数组中存储的元素
private Object[] elementData = null;
private int count ;
// ArrayList 的构造方法 通过构造方法 可以得到这个类的对象
// 有参构造方法
public ArrayList(int i){
if(i <= 0 ){
throw new RuntimeException("数组的长度不能小于等于0");
}else{
this.elementData = new Object[i];
this.size = 0 ; // 集合ArrayList的大小;
}
}
// 无参构造方法
public ArrayList(){
this(DEFAULT_SIZE); // this 会调用本类中 相同参数(相同的参数个数和参数类型)的构造方法;
}
/** ArrayList 其他方法分析
* 目标方法:
* size(); Array的length就是ArrayList的大小
* get(int index); Array的【index-1】就是 ArrayList的第index位元素
* add(Object o) ; 这个方法是在数组的末尾顺序添加一个元素; 找到数组的长度size,将array【size-1】= Object
* add(int index , Object o); 这个方法是在数组的指定位置添加一个元素;找到index位,将index位起往后挪一位,并将array【index】=Object
* remove(int index); 这个方法是 删除指定位上的元素,直接将这个位至最后的元素往前挪移一位。
*
* 工具方法:
* argumentCheck(int index); 判断输入的参数是否合法;比如传入的参数不能比数组长度大,或者不能为负数等
* ensureCapacity(); 判断当前数组的长度是否足够大,能再容纳下一个元素。
*
* */
// 对传入的参数进行验证是否合法 如果输入的参数不合法 就抛出异常
public void argumentCheck(int index){
if(index >= size || index < 0 ){ // 此处我觉得需要 ‘=’ 因为 index 我觉得是下标
throw new IndexOutOfBoundsException("插入的下标是:"+index +",但ArrayLsit的长度是:"+size);
}
}
// 判断是否数组是否溢出的方法 如果数组现在的长度小于所需的最小长度,就需要对数组进行扩容
public void ensureCapacity(int minCapacity){
int length = elementData.length; // 得出当前数组的长度
if(minCapacity > length){
int newCapacity = length * 3 / 2 + 1 ; //你是否对此有疑问?得出的结果会不会是小数? 答案是不会的,java中算术运算符“/”;两个int类型相除,结果一定是int类型
if(minCapacity > newCapacity ){
newCapacity = minCapacity ;
}
count++;
System.out.println("扩容"+count+"次");
elementData = Arrays.copyOf(elementData, newCapacity);//此处为什么用Arrays.copyOf()而不用System.arraycopy()?
// Arrays.copyOf(): 不仅仅copy数组中的元素,还会创建一个新的数组来存放copy的对象
// System.arraycopy():仅仅是copy数组中的元素,不会新建一个数组对象,也不会改变原有的数组长度。
// 在原有数组长度不够的情况下,只能选择新建一个数组,并将原有的数组复制到新数组的办法来解决。
}
}
// 得到ArrayList 大小的方法 ; 此处的size 不是Array的length,而是ArrayList中元素的个数
public int size(){
return size;
}
// 传入下标得到元素
public Object get(int index){
argumentCheck(index); //需要判断传入的参数是否合法;
return elementData[index];
}
// 按顺序在数字尾部添加元素
public void add(Object o){
ensureCapacity(size+1); // 判断是否会溢出
elementData[size++] = o ; //此处使用 size++ 的好处:elementData[size+1];size++;
}
public void add(int index, Object o){ //这个地方需要搞清楚index的含义:index在此处是下标的意思
argumentCheck(index); //判断输入的下标是否合法 --->
// 刚开始的时候 ; 我觉得这个地方不需要加这个判断,因为ArrayList是动态增长的;
// 我还需要想明白这个问题;
ensureCapacity(size+1); // 判断是否会溢出
int moveLength = size - (index + 1) + 1; // 此处index是下标;下标是从0开始计算的;所以第n位的下标就是(n-1);所以,n = index + 1
// 此处的 +1 刚开始没想明白,后来组长给举了个例子,1-3 有三个数,但不是通过3-1=2 算出来的
System.arraycopy(elementData, index, elementData, index+1, moveLength );
elementData[index] = o ;
size++;
}
public Object remove(int index){
argumentCheck(index); //判断输入的下标是否合法
Object o = elementData[index];
System.arraycopy(elementData, index, elementData, index-1, size-index);
elementData[size] = null ;
size--;
return o;
}
public Iterator iterator(){
return new Iterator(){
private int index = 0 ;
@Override
public Object next(){
return elementData[index++];
}
@Override
public boolean hasNext() {
return index < size ;
}
};
}
public static void main(String [] args){
ArrayList al = new ArrayList();
al.add(1);
al.add(2);
al.add(4);
al.add(5);
al.add(6);
al.add(7);
al.add(2,3);
al.add(8);
al.add(9);
al.add(10);
al.add(11);
al.add(13);
al.add(9,12);
al.add(14);
al.add(15);
al.remove(9);
for(int i = 0 ; i < al.size() ; i++ ){
System.out.println(al.get(i));
}
System.out.println("al的size是"+al.size());
System.out.println(al.get(15));
}
}