JavaSE之List集合及相关面试题

本文详细介绍了List集合的概念、特点,包括ArrayList和LinkedList的底层实现、扩容机制以及面试中常考的关于构造函数、容量扩展等问题。同时强调了理解集合底层源码的重要性。
摘要由CSDN通过智能技术生成

1. List集合的概念和特点

1.1 概念

1. 有序集合(有序指的是存储顺序)。

2.用户可以控制列表中每个元素的插入位置,可以通过整数索引来访问元素并搜索列表中的元素。

3.与Set集合不同,列表可以存储重复的元素。

1.2 特点

1.存取有序

2.可以重复

3.有索引

2. List集合特有的方法

方法名用途
void add(int index,E element)在集合中指定的位置插入指定的元素。
E remove(int index)删除指定索引处的元素并返回被删除的元素。
E set(int index,E element)修改指定索引处的元素并返回被修改的元素。
E get(int index)返回指定索引处的元素。

3. List集合子类的特点

3.1 ArrayList集合

底层是数组结构实现,查询快,增删慢。

3.2 LinkedList集合

底层是链表结构实现,查询慢,增删快。

4. 面试题

关于构造函数

JDK 7以无参构造方法创建ArrayList时,直接创建长度是10的Object[]数组elementData.

JDK 8以无参构造创建ArrayList时,实际上初始化赋值的是一个空数组。当真正对数组进行添加操作时,才开始分配容量。所以向数组添加第一个元素时,数组容量扩容为10.

//判断是否需要扩容
private void ensureExplicitCapacity(int minCapacity) {
    modCount++;
   
    if (minCapacity - elementData.length > 0)
    //调用grow方法进行扩容,调用此方法代表已经开始扩容了
        grow(minCapacity);
}

4.1 ArrayList无参数构造器构造,add一个值进去,此时的数组大小是多少,下一次扩容前最大可用大小是多少?

答:此时的数组大小是1,下一次最大可用大小是10,当add第一个值进去时,数组可用大小被扩容到10.

4.2 如果连续往 list 里面新增值,增加到第 11 个的时候,数组的大小是多少?

根据ArrayList的源码

private void grow(int minCapacity) {
    int oldCapacity = elementData.length;
    // oldCapacity为旧容量,newCapacity为新容量,将新容量更新为旧容量的1.5倍
    int newCapacity = oldCapacity + (oldCapacity >> 1);
    if (newCapacity - minCapacity < 0)
            newCapacity = minCapacity;
    if (newCapacity - MAX_ARRAY_SIZE > 0)
        newCapacity = hugeCapacity(minCapacity);
    // minCapacity is usually close to size, so this is a win:
    elementData = Arrays.copyOf(elementData, newCapacity);
}

可知当增加到11时,此时数组容量是10,不够要扩容,根据源码int newCapacity = oldCapacity + (oldCapacity >> 1);10+10/2=15,所以数组大小被扩充到15。

4.3 数组初始化,被加入一个值后,如果使用 addAll 方法,一下子加入 15 个值,那么最终数组的大小是多少?

答:当数组添加一个值后,实际大小是1,最大可用大小是10,现在加入15个值,期望数组大小为16,此时数组大小为10,根据扩容公式(见上)扩容后大小为15,扩容后大小<期望大小,根据源码

 if (newCapacity - minCapacity < 0)
            newCapacity = minCapacity;

如果扩容后的值<期望值,扩容后的大小就等于期望值。

4.4 现在有一个很大的数组需要拷贝,原数组大小是 5k,请问如何快速拷贝?

答:数组较大,如果新建数组时,不指定数组大小,会导致频繁扩容,造成拷贝效率低下,

所以在新建数组时,指定新数组大小为5K即可。

4.5 ArrayList和LinkedList对比

4.5.1 ArrayList 和 LinkedList 有何不同?

从底层数据结构来看ArrayList底层是数组,LinkedList底层是双向链表。ArrayList新增时,会先计算再决定是否扩容,把新增的值直接赋值到数组上,LinkedList只需要改变插入节点和其前后节点所指向位置即可。

4.5.2 ArrayList 和 LinkedList 两者有没有最大容量?

答:ArrayList有最大容量,最大容量为Integer的最大值,超过这个值,JVM不会为数组分配内存空间的,LinkedList底层是双向链表,理论上是无限大的,但源码中,LinkedList使用的是int类型,这也说明LinkedList最大容量不能超过Integer的最大值,不然会溢出。

4.5.3 ArrayList 和 LinkedList 是如何对 null 值进行处理的

ArrayList允许null新增、删除。从头开始找到第一个null值删除;LinkedList对null值没有特殊校验,允许新增和删除。

5. 总结

面试时面试官喜欢问集合底层源码的知识,建议多看多分析。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值