互联网架构-Java8集合框架源码分析-037:Arraylist集合源码深度解析

1 Arraylist集合课程基本的介绍

课程内容:
1.Java8中Arraylist与Vector集合区别
2.Java8中ArraylistAdd方法数组如何实现扩容
3.Java8中ArraylistRemove方法源码分析
4.Java8中完全手写Java8 Arraylist框架

2 Arraylist集合构造函数源码分析

基本原理思想:
Arraylist集合底层使用动态数组(object类型)实现,随机查询效率非常快,插入和删除需要移动整个数组、效率低。
ArrayList不是线程安全的集合; Vector是线程安全的集合。

3 Arraylist集合框架底层数组扩容原理

public class ListTest001 {
    public static void main(String[] args) {
        Object[] elementData = {"1", "2", "3"};
        System.out.println("数组扩容前:");
        for (Object e : elementData) {
            System.out.println("elementData:" + e);
        }
        int newCapacity = 10;
        // 对原数组实现扩容,将旧的数组数据复制到新的数组中,返回新的数组,容量为newCapacity
        Object[] objects = Arrays.copyOf(elementData, newCapacity);
        System.out.println("数组扩容后:");
        for (Object o : objects) {
            System.out.println("objects:" + o);
        }

    }
}

运行结果:
在这里插入图片描述

4 Arraylist集合框架数组扩容

Arraylist数组扩容分析

  1. 第一次添加数据的时候,数组默认扩容是为10;
  2. int newCapacity = oldCapacity + (oldCapacity >> 1);
    oldCapacity=10;
    int newCapacity = oldCapacity + oldCapacity/2;
    newCapacity=15
    新数组容量是原数组容量的1.5倍
    数组的最大容量:Integer的最大值2^32

System.arraycopy(src, srcPos, dest, destPos, length);
src 原数组 srcPost 起始位置 dest目标数组 destPos 目标数组放置的起始位置 length 复制长度

5 手写简单版本ArrayList实现基本功能

public interface MayiktList<E> {
    /**
     * 集合大小
     * @return
     */
    int size();

    /**
     * 添加元素
     * @param e
     * @return
     */
    boolean add(E e);

    /**
     * 使用下标查询元素
     * @param index
     * @return
     */
    E get(int index);

    /**
     * 使用下标删除元素
     * @param index
     * @return
     */
    public E remove(int index);

}
public class MayiktArrayList<E> implements MayiktList<E> {

    /**
     * elememtData数组存放ArrayList所有数据,transient作用不能被序列化
     */
    transient Object[] elementData;

    /**
     * 给数组容量赋值为空
     */
    private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};

    /**
     * 数组初始容量默认为0
     */
    private int size;

    /**
     * 数组默认容量大小为10
     */
    private static final int DEFAULT_CAPACITY = 10;

    /**
     * 2^32-8
     */
    private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;


    public MayiktArrayList() {
        elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
    }

    @Override
    public int size() {
        return size;
    }

    @Override
    public boolean add(E e) {
        // 对数组实现扩容
        ensureCapacityInternal(size + 1);
        // 对数组元素赋值
        elementData[size++] = e;
        return true;
    }

    @Override
    public E get(int index) {
        return (E) elementData[index];
    }

    @Override
    public E remove(int index) {
        // 检查下标位置是否越界
        rangeCheck(index);
        // 获取要删除的对象
        E oldValue = get(index);
        // 计算移动的位置
        int numMoved = size - index - 1;
        // 判断删除的数据不是最后一个,将删除数据后面的数据往前移动一位
        if (numMoved > 0) {
            System.arraycopy(elementData, index + 1, elementData, index, numMoved);
        }
        // 如果numMoved为0的情况下,后面不需要往前移动,直接将最后一条数据赋值为null
        elementData[--size]= null;// clear to let GC do its work
        return null;
    }

    public void rangeCheck(int index) {
        if (index > size) {
            throw new IndexOutOfBoundsException("数组越界,下标位置index:" + index);
        }
    }

    private void ensureCapacityInternal(int minCapacity) {
        // 添加元素的时候,如果数组为空
        if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
            minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity);
        }
        ensureExplicitCapacity(minCapacity);
    }

    private void ensureExplicitCapacity(int minCapacity) {
        // 第一次 10-0>0
        if (minCapacity - elementData.length > 0) {
            // 对数组实现扩容
            grow(minCapacity);
        }

    }

    private void grow(int minCapacity) {
        // 获取数组长度
        int oldCapacity = elementData.length;
        // 新容量=原来容量+原来容量一半
        int newCapacity = oldCapacity + (oldCapacity >> 1);
        // 第一次:0-10<0 第一次对数组容量初始化操作
        if (newCapacity - minCapacity < 0) {
            // 新容量=10
            newCapacity = minCapacity;
        }
        if (newCapacity - MAX_ARRAY_SIZE > 0) {
            newCapacity = hugeCapacity(minCapacity);
        }
        // 开始对数组实现扩容,将旧的数组数据复制到新的数组中
        elementData = Arrays.copyOf(elementData, newCapacity);
    }

    /**
     * 判断最小初始化容量,限制数组扩容最大值
     *
     * @param minCapacity
     * @return
     */
    private static int hugeCapacity(int minCapacity) {
        if (minCapacity < 0) // overflow
            throw new OutOfMemoryError();
        return (minCapacity > MAX_ARRAY_SIZE) ?
                Integer.MAX_VALUE :
                MAX_ARRAY_SIZE;
    }
}
public class ListTest {
    public static void main(String[] args) {
        MayiktArrayList<String> stringMayiktArrayList = new MayiktArrayList<String>();
        for (int i = 0; i < 10; i++) {
            stringMayiktArrayList.add("蚂蚁课堂" + i);
        }
        stringMayiktArrayList.add("蚂蚁课堂11");
        System.out.println("删除数据之前:");
        for (int i = 0; i < stringMayiktArrayList.size(); i++) {
            System.out.println(stringMayiktArrayList.get(i));
        }
        stringMayiktArrayList.remove(2);
        System.out.println("==============");
        System.out.println("删除数据之后:");
        for (int i = 0; i < stringMayiktArrayList.size(); i++) {
            System.out.println(stringMayiktArrayList.get(i));
        }
    }
}

运行结果:
在这里插入图片描述

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值