首页 > 编程语言 >ArrayList源码分析(底层数据结构,成员变量,构造方法)以及面试题(基于JDK1.8)

ArrayList源码分析(底层数据结构,成员变量,构造方法)以及面试题(基于JDK1.8)

时间:2024-10-14 22:46:07浏览次数:7  
标签:实例 面试题 Object 构造方法 ArrayList elementData 源码 数组

要分析Arraylist,我们首先要从它的底层数据结构实现出发,再结合其底层源码,可能能让读者理解的更加深刻一点。

1,底层数据结构(数组)

Arraylist底层是基于动态数组实现的。

数组是一种使用连续储存空间储存相同数据类型的线性数据结构。

面试题1

为什么数组索引从0开始不从1开始?

分析:要回答这个问题,我们首先要了解一个知识点,即数组的寻址公式。

解释一下当中的变量,baseAddress:为数组的首地址,i即为寻址为数组中的第几个元素(索引),dataTypeSize即为当前数组对应数据结构的字节数。

如果数组索引从1开始,意味着寻址公式会发生变化。

意味着相比于未发生变化的寻址公式,每次计算机CPU都需要多执行一次i-1操作。

但是次数一多,成千上万,上百万千万后,对执行速度还是有影响。所以归纳出标准答案。

标准答案:

2,ArrayList源码分析

1,ArrayList源码分析-成员变量

private static final int DEFAULT_CAPACITY = 10;
//默认初始的容量

private static final Object[] EMPTY_ELEMENTDATA = {};
//用于空实例的数组实例

private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};
//用于默认大小空实例的共享空数组实例。

transient Object[] elementData;
//存储ArrayList元素的数组缓冲区。ArrayList的容量是这个数组的长度。

private int size;
//ArrayList的大小(它包含的元素数量)

我们一般关注ArrayList源码中这五个成员变量,后面解释源码的时候会用到。

2,ArrayList源码分析-构造方法

1,无参构造方法

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

读者看到这个elementData有没有很熟悉,没错就是成员变量中的存储ArrayList元素的数组缓冲区,后面这个常量就是默认大小的空数组实例,即调用空参构造方法会创建一个长度为零的数组赋给arrayList。

2,有参构造方法

1,传入INT指定长度
    public ArrayList(int initialCapacity) {
        if (initialCapacity > 0) {
            this.elementData = new Object[initialCapacity];
            //如果传入一个INT大于零,则创建该对应整形长度大小的数组
            // 赋给arraylist中的elementData
        } else if (initialCapacity == 0) {
            this.elementData = EMPTY_ELEMENTDATA;
            //如果传入一个INT等于零,则将常量EMPTY_ELEMENTDATA(空实例的数组实例)
            //赋给arraylist中的elementData
        } else {
            throw new IllegalArgumentException("Illegal Capacity: " +
                    initialCapacity);
            //其它情况则是传入一个INT小于零,当然是不被允许的,所以抛出异常
        }
    }
2,传入集合
    public <E> ArrayList(Collection<? extends E> c) {
        elementData = c.toArray();
        //toArray方法即将对象c转为数组
        if ((size = elementData.length) != 0) {
            // c.toArray 可能并没有返回一个object对象,因此要做出判断
            if (elementData.getClass() != Object[].class)
                //传入的属性不为Object,调用Arrays.copyOf方法,将Object属性拷贝后转为数组
                // 再赋值给elementData
                elementData = Arrays.copyOf(elementData, size, Object[].class);
        } else {
            // c.toArray()是空的,转为空实例的数组实例,赋值给elementData
            this.elementData = EMPTY_ELEMENTDATA;
        }
    }

面试题2,ArrayList list = new ArrayList<>(10)中list扩容几次?

分析:读者可以很轻易看出来,该程序调用了ArrayList 中的有参构造方法中的传入INT指定长度的方法,执行以下逻辑,if (initialCapacity > 0) {  this.elementData = new Object[initialCapacity];},创建该对应整形长度大小的数组, 赋给arraylist中的elementData,并未进行扩容。

参考答案:该语句只是声明和实例了一个ArrayList,指定了容量为10,并未进行扩容。

下一篇文章再和大家阅读关于ArrayList扩容,以及添加元素的源码。

标签:实例,面试题,Object,构造方法,ArrayList,elementData,源码,数组
From: https://blog.csdn.net/weixin_52469927/article/details/142834434

相关文章