ArrayList

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);
        }
    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值