ArrayList和LinkedList的面试题

本文探讨了ArrayList的线程不安全原因,解释了在多线程环境下可能出现的问题。接着,讨论了ArrayList的动态扩容机制,指出其可以无限添加元素的原因。最后,对比分析了ArrayList和LinkedList的时间复杂度,包括get、add、add(index)和remove操作的性能差异。
摘要由CSDN通过智能技术生成

一、ArrayList为什么是线程不安全的?

ArrayList在添加一个元素的时候,它可能会有两步来完成:

1. 在 Items[Size] 的位置存放此元素;
2. 增大 Size 的值。
在单线程运行的情况下,如果 Size = 0,添加一个元素后,此元素在位置 0,而且 Size=1;
而如果是在多线程情况下,比如有两个线程,线程 A 先将元素存放在位置 0。但是此时 CPU 调度线程A暂停,线程 B 得到运行的机会。线程B也向此 ArrayList 添加元素,因为此时 Size 仍然等于 0 (注意哦,我们假设的是添加一个元素是要两个步骤哦,而线程A仅仅完成了步骤1),所以线程B也将元素存放在位置0。然后线程A和线程B都继续运行,都增加 Size 的值。 那好,现在我们来看看 ArrayList 的情况,元素实际上只有一个,存放在位置 0,而 Size 却等于 2。这就是“线程不安全”了。


二、ArrayList能否无限添加元素?会抛异常吗?

当我们使用ArrayList时,我们可以无限的往里添加元素,这是为什么呢?它底层是由数组实现的,使用无参构造方法时系统会默认提供默认参数10,而使用有参构造函数时我们会指定大小,我们都是知道使用数组时当添加的元素个数大于数组的初始化长度时会报数组下标越界异常,那么ArrayList为什么不会呢?因为ArrayList会自动为其扩容,扩容后的大小是int newCapacity = (oldCapacity * 3)/2 + 1;  

三、ArrayList和LinkedList的时间复杂度

ArrayList 是线性表(数组)
get() 直接读取第几个下标,复杂度 O(1)
add(E) 添加元素,直接在后面添加,复杂度O(1)
add(index, E) 添加元素,在第几个元素后面插入,后面的元素需要向后移动,复杂度O(n)
remove()删除元素,后面的元素需要逐个移动,复杂度O(n)

LinkedList 是链表的操作
get() 获取第几个元素,依次遍历,复杂度O(n)
add(E) 添加到末尾,复杂度O(1)
add(index, E) 添加第几个元素后,需要先查找到第几个元素,直接指针指向操作,复杂度O(n)
remove()删除元素,直接指针指向操作,复杂度O(1)


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值