更新时间:2020-07-06 15:50:51 来源:极悦 浏览2160次
1、ArrayList和LinkedList的区别?
是否保证线程安全:ArrayList和LinkedList都是不同步的,也就是不保证线程安全;
底层数据结构:Arraylist底层使用的是Object数组;LinkedList底层使用的是双向循环链表数据结构;
插入和删除是否受元素位置的影响:①ArrayList采用数组存储,所以插入和删除元素的时间复杂度受元素位置的影响。比如:执行add(E e)方法的时候,ArrayList会默认在将指定的元素追加到此列表的末尾,这种情况时间复杂度就是O(1)。但是如果要在指定位置i插入和删除元素的话(add(int index,E element))时间复杂度就为O(n-i)。因为在进行上述操作的时候集合中第i和第i个元素之后的(n-i)个元素都要执行向后位/向前移一位的操作。②LinkedList采用链表存储,所以插入,删除元素时间复杂度不受元素位置的影响,都是近似O(1)而数组为近似O(n)。
是否支持快速随机访问:LinkedList不支持高效的随机元素访问,而ArrayList实现了RandmoAccess接口,所以有随机访问功能。快速随机访问就是通过元素的序号快速获取元素对象(对应于get(int index)方法)。
内存空间占用:ArrayList的空间浪费主要体现在在list列表的结尾会预留一定的容量空间,而LinkedList的空间花费则体现在它的每一个元素都需要消耗比ArrayList更多的空间(因为要存放直接后继和直接前驱以及数据)。
补充:ArrayList的增删未必就是比LinkedList要慢:
如果增删都是在末尾来操作【每次调用的都是remove()和add()】,此时ArrayList就不需要移动和复制数组来进行操作了。如果数据量有百万级的时,速度是会比LinkedList要快的。
如果删除操作的位置是在中间。由于LinkedList的消耗主要是在遍历上,ArrayList的消耗主要是在移动和复制上(底层调用的是arrayCopy()方法,是native方法)。LinkedList的遍历速度是要慢于ArrayList的复制移动速度的如果数据量有百万级的时,还是ArrayList要快。
2、ArrayList实现RandomAccess接口有何作用?为何LinkedList却没实现这个接口?
RandomAccess接口只是一个标志接口,只要List集合实现这个接口,就能支持快速随机访问。实现RandomAccess接口的List集合采用一般的for循环遍历,而未实现这接口则采用迭代器,即ArrayList一般采用for循环遍历,而LinkedList一般采用迭代器遍历;
ArrayList用for循环遍历比iterator迭代器遍历快,LinkedList用iterator迭代器遍历比for循环遍历快。所以说,当我们在做项目时,应该考虑到List集合的不同子类采用不同的遍历方式,能够提高性能。
Java集合类中元素的访问分为随机访问和顺序访问。随机访问一般是通过index下标访问,行为类似数组的访问。而顺序访问类似于链表的访问,通常为迭代器遍历。
以List接口及其实例为例。ArrayList是典型的随机访问型,而LinkedList则是顺序访问型。List接口既定义了下标访问方法又定义了迭代器方法。所以其实例既可使用下标随机访问也可以使用迭代器进行遍历。但这两种方式的性能差异很明显。
RandomAccess接口
JDK中的RandomAccess接口是一个标记接口,它并未定义方法。其目的是用于指示实现类具有随机访问特性,在遍历时使用下标访问较迭代器更快。
3.ArrayList的扩容机制?
当使用add方法的时候首先调用ensureCapacityInternal方法,传入size+1进去,检查是否需要扩充elementData数组的大小;
newCapacity=扩充数组为原来的1.5倍(不能自定义),如果还不够,就使用它指定要扩充的大小minCapacity,然后判断minCapacity是否大于MAX_ARRAY_SIZE(Integer.MAX_VALUE-8),如果大于,就取Integer.MAX_VALUE;
扩容的主要方法:grow;
ArrayList中copy数组的核心就是System.arraycopy方法,将original数组的所有数据复制到copy数组中,这是一个本地方法。
5.Array和ArrayList有何区别?什么时候更适合用Array?
Array可以容纳基本类型和对象,而ArrayList只能容纳对象;
Array是指定大小的,而ArrayList大小是固定的。
什么时候更适合使用Array:
4.如果列表的大小已经指定,大部分情况下是存储和遍历它们;
对于遍历基本数据类型,尽管Collections使用自动装箱来减轻编码任务,在指定大小的基本类型的列表上工作也会变得很慢;
如果你要使用多维数组,使用[][]比List>更容易。
5.什么是Iterator?
一些集合类提供了内容遍历的功能,通过java.util.Iterator接口。这些接口允许遍历对象的集合。依次操作每个元素对象。当使用Iterators时,在获得Iterator的时候包含一个集合快照。通常在遍历一个Iterator的时候不建议修改集合本省。
6.Iterator与ListIterator有什么区别?
Iterator:只能正向遍历集合,适用于获取移除元素。ListIerator:继承Iterator,可以双向列表的遍历,同样支持元素的修改。
Iterator可以遍历Set和List集合,而ListIterator只能遍历List
ListIterator从Iterator接口继承,然后添加了一些额外的功能,比如添加一个元素、替换一个元素、获取前面或后面元素的索引位置。
7.什么叫做快速失败特性?
从高级别层次来说快速失败是一个系统或软件对于其故障做出的响应。一个快速失败系统设计用来即时报告可能会导致失败的任何故障情况,它通常用来停止正常的操作而不是尝试继续做可能有缺陷的工作。当有问题发生时,快速失败系统即时可见地发错错误告警。在Java中,快速失败与iterators有关。如果一个iterator在集合对象上创建了,其它线程欲“结构化”的修改该集合对象,并发修改异常(ConcurrentModificationException)抛出。
8.为什么Vector类认为是废弃的或者是非官方地不推荐使用?或者说为什么我们应该一直使用ArrayList而不是Vector?
默认情况下你是非同步访问的,Vector同步了每个方法,你几乎从不要那样做,通常有想要同步的是整个操作序列。同步单个的操作也不安全(如果你迭代一个Vector,你还是要加锁,以避免其它线程在同一时刻改变集合).而且效率更慢。当然同样有锁的开销即使你不需要,这是个很糟糕的方法在默认情况下同步访问。你可以一直使用Collections.sychronizedList来装饰一个集合。
事实上Vector结合了“可变数组”的集合和同步每个操作的实现。这是另外一个设计上的缺陷。Vector还有些遗留的方法在枚举和元素获取的方法,这些方法不同于List接口,如果这些方法在代码中程序员更趋向于想用它。尽管枚举速度更快,但是他们不能检查如果集合在迭代的时候修改了,这样将导致问题。尽管以上诸多原因,Oracle也从没宣称过要废弃Vector。
9.哪些集合类提供对元素的随机访问?
ArrayList、HashMap、TreeMap和HashTable类提供对元素的随机访问。
10.哪些集合类是线程安全的?
Vector、HashTable、Properties和Stack是同步类,所以它们是线程安全的,可以在多线程环境下使用。
以上就是极悦java培训机构的小编针对“2020年Java集合类面试题及答案”的内容进行的回答,希望对大家有所帮助,如有疑问,请在线咨询,有专业老师随时为你服务。
0基础 0学费 15天面授
Java就业班有基础 直达就业
业余时间 高薪转行
Java在职加薪班工作1~3年,加薪神器
工作3~5年,晋升架构
提交申请后,顾问老师会电话与您沟通安排学习