ArrayList-Java八股面试(一)

系列文章目录

第一章 ArrayList-Java八股(一)



前言

准备春招实习的小伙伴可以一起交流学习,动态每日更新算法题。


一、ArrayList的扩容

其实ArrayList底层就是一个数组,为了方便的讲清楚扩容机制,以下内容会采用图解的方式来说明。

1.1 ArrayList的初始化

这是jdk1.8中ArrayList的空参构造方法的说明,构造一个大小为10的空列表,请注意这个构造方法是已经进行了一次扩容。
在这里插入图片描述


模拟构建一个ArrayList集合。
在这里插入图片描述


不断的往集合中add元素,直到添加满,总共为10个元素。
在这里插入图片描述


1.2 ArrayList的扩容

在添加第11个元素时,集合会扩容为15个元素(一般情况下达到上限之后会扩容为原先大小的1.5倍,但不是绝对,在addAll方法中不适用此规则),具体流程是新建一个新的数组,然后做数据迁移,后面会再详细说明。
在这里插入图片描述


1.3 扩容大小计算规则

如何计算1.5倍,在是奇数大小的情况下

在这里插入图片描述


1.4扩容流程拆分

对于扩容分为两个步骤先看扩容的结果
在这里插入图片描述

第16个元素加入之后集合大小扩容为22个。
那么这期间可以拆分为两个步骤:
在这里插入图片描述

  1. 新建一个大小为22的新数组
  2. 数组内容的迁移

1.5 add方法源码

在这里插入图片描述


1.6 addAll()方法

而对于addAll()方法扩容规则会有所变化。
在这里插入图片描述

上述代码分别对一个空集合使用addAll()方法,参数个数为两组分别为3个和11个,
那么对于数量为3的集合来说扩容为10个,而对于数量为11的集合来说扩容数量为11个。

在这里插入图片描述

也就是说在使用addAll()方法来说会在下一次扩容数量和需要添加的数量中取一个最大值

二.Fail-Fast/Safe 特性

Fail-safe和Fail-fast,是多线程并发操作集合时的一种失败处理机制。

Fail-fast : 表示快速失败,在集合遍历过程中,一旦发现容器中的数据被修改了,会立刻抛出ConcurrentModificationException异常

在这里插入图片描述

2.1 Fail-Fast代码演示

代码使用增强for来进行遍历,而其底层其实为迭代器进行遍历。

在这里插入图片描述

在如下循环中加入断点,并在idea中开启两次,也就是两个进程来模拟多线程处理,当程序一停到这边时,程序二完成添加操作。
在这里插入图片描述

程序一抛出ConcurrentModificationException异常
在这里插入图片描述

2.2 Fail-Fast源码

以下是迭代器的源码,每一次遍历都会使用next()方法取到下一个元素,而当中checkForCmodification()就是抛出此异常的方法。

在这里插入图片描述

进入其方法之后,可以看到两个参数modCount和expectedModCount,在初始化时modCount赋值给expectedModCount,也就是说二者其实是相等的,而modCount代表的意思是对集合的操作次数,而expectedModCount代表的是迭代器对集合操作的次数,一旦在程序二在运行时,modCount就发生了变化,因此会抛出异常。

在这里插入图片描述


2.3 Fail-Safe源码

在这里插入图片描述

在这里我们可以看到数组会先赋值给snapshot快照,而后面参与迭代器计算的就是snapshot而不是es。

在next方法中完全是对snapshot进行操作。

public E next() {
    if (! hasNext())
        throw new NoSuchElementException();
    return (E) snapshot[cursor++];
}

三. LinkedList

3.1 ArrayList和LinkedList区别

其实两种集合都一样,ArrayList底层是数组,而LinkedList底层为链表。
在这里插入图片描述

3.2 cpu缓存局部性原理

在这里插入图片描述

比如说计算a+b,那么在没有缓存的情况下,cpu需要读取在内存a寄存器和b寄存器中的数据,计算完之后放入c寄存器,而IO都是非常耗时的操作。
而在缓存的情况下,将a和b读入之后,那么a和b以及计算后的c会存入缓存中,那么下一次在使用abc的值时会直接存缓存中读取,大大减少了IO操作。
但是在读取时,比如说需要读取数组索引[0]的的数据,那么cpu在读取时,会连续读取一段数据,可能会读取完整个数组,而链表在内存的地址是不连续的,所以没有办法利用局部性原理。

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值