java数据结构1------深入学习ArrayList

目录

一、概念

二、源码分析

1、属性

2、构造器

 ①空构造

②指定初始容量(initialCapacity)构造器

②参数为Collection的构造器

3、常用方法

①public boolean add(E e)

②public void add(int index, E element)

③其他方法

三、总结


一、概念

java.util.ArrayList 是Java中的常用类,它实现了List接口,能够存储任意类型的数据。ArrayList底层是通过数组实现的,因此它具有快速随机访问的特性。

二、源码分析

1、属性

java数据结构1------深入学习ArrayList_第1张图片

DEFAULT_CAPACITY(默认容量)是一个常量10

EMPTY_ELEMENTDATA 与 DEFAULTCAPACITY_EMPTY_ELEMENTDATA 都是常量空集合

elementData 是ArrayList内部维护的数组

size为ArrayList的长度

2、构造器

    public ArrayList() {
        this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
    }


    public ArrayList(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);
        }
    }

    public ArrayList(Collection c) {
        elementData = c.toArray();
        if ((size = elementData.length) != 0) {
            // c.toArray might (incorrectly) not return Object[] (see 6260652)
            if (elementData.getClass() != Object[].class)
                elementData = Arrays.copyOf(elementData, size, Object[].class);
        } else {
            // replace with empty array.
            this.elementData = EMPTY_ELEMENTDATA;
        }
    }
 ①空构造

将维护的数组(elementData)赋值为DEFAULTCAPACITY_EMPTY_ELEMENTDATA

②指定初始容量(initialCapacity)构造器

initialCapacity为负数抛出异常

initialCapacity为0,将维护的数组(elementData)赋值为空集

initialCapacity为正数,将维护的数组(elementData)赋值为长度为initialCapacity的数组

②参数为Collection的构造器

1、通过参数获取新的数组赋值给维护的数组(elementData)

2、将size刷新并判断长度,为零则与new ArrayList(0)一样处理(将维护的数组(elementData)赋值为空集)不为零并且判断不是

Object[]类型,则变为Object[]类型。

3、常用方法

①public boolean add(E e)
    //添加单个元素
    public boolean add(E e) {
        //确保容量够用
        ensureCapacityInternal(size + 1); 
        //赋值
        elementData[size++] = e;
        return true;
    }

    //确保容量够用,参数是最小容量条件
    private void ensureCapacityInternal(int minCapacity) {
        //计算容量后确定容量
        ensureExplicitCapacity(calculateCapacity(elementData, minCapacity));
    }

    //计算容量
    private static int calculateCapacity(Object[] elementData, int minCapacity) {
        //前面讲过,如果是空构造即new ArrayList(),就会赋值DEFAULTCAPACITY_EMPTY_ELEMENTDATA
        if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
            //默认容量与最小容量条件对比,返回大的
            return Math.max(DEFAULT_CAPACITY, minCapacity);
        }
        return minCapacity;
    }

    //确定容量,参数是最小容量条件
    private void ensureExplicitCapacity(int minCapacity) {
        //添加、删除、修改等操作时,modCount的值就会增加,modCount主要目的就是用来限制用户在迭代时修改列表,造成数据错乱
        modCount++;

        //若计算的容量大于实际容量则扩容
        if (minCapacity - elementData.length > 0
            grow(minCapacity);
    }

    //扩容
    private void grow(int minCapacity) {
        // 现在维护的数组的容量
        int oldCapacity = elementData.length;
        // 新容量为之前的1.5倍
        int newCapacity = oldCapacity + (oldCapacity >> 1);
        // 新容量若不够,使用需求容量
        if (newCapacity - minCapacity < 0)
            newCapacity = minCapacity;
        // 这里一定要用减法,不是直接比较大小(可以想新容量负数时)
        if (newCapacity - MAX_ARRAY_SIZE > 0)
            newCapacity = hugeCapacity(minCapacity);
        // 扩容到指定大小
        elementData = Arrays.copyOf(elementData, newCapacity);
    }
②public void add(int index, E element)
    public void add(int index, E element) {
        //检查此下标是否存在
        rangeCheckForAdd(index);
        //确定容量
        ensureCapacityInternal(size + 1);  
        //将index开始到最后的元素都向后复制到下一位
        System.arraycopy(elementData, index, elementData, index + 1,
                         size - index);
        //赋值
        elementData[index] = element;
        size++;
    }
③其他方法
public E get(int index): 1、检查index是否合理  2、直接在维护的数组中查index 返回
public E remove(int index):1、检查index是否合理  2、通过System.arraycopy把index后面每个元素向前移动一位 3、把末尾赋值null,size减1
public E set(int index, E element): 1、检查index是否合理 2、直接在维护的数组对下标为index的元素赋值

由于过于简单,这里不再列举

三、总结

ArrayList底层是基于数组实现的,在new ArrayLIst()后容量是0,在添加第一个元素时会默认容量为10,扩容时默认扩容到原来的1.5倍。

ArrayList的扩容机制是通过拷贝数组实现的,删除某个元素是也要进行大量拷贝,所以插入元素或者删除某个元素时效率会很低,而在查询或者更新是效率很高。

你可能感兴趣的:(数据结构,java)