关于List集合,这份总结很全面

第一章 List集合总结1.1 引导语List 是工作中最常用的集合类型之一 , 面试的时候 , 大家也会被问到各种各样的问题 , 但是一般大多数情况下 , 只要你看了解过List集合源码 , 对List集合总结结构和源码有所了解的话,一般都问题不大 。
1.2 谈一下你是如何理解ArrayList集合的?很多面试官非常喜欢问这样的问题,主要考察同学们平时工作学习过程中有没有深入思考,经常性的总结.关于ArrayList集合起始内容还是比较多的,建议大家先回答ArrayList的总体的结构,再找个自己很熟悉的理解很深入的细节作为入口,夸夸其谈,就ok了.
比如:
ArrayList 底层数据结构是个数组 , 而数组有索引,内存元素存储空间是连续的 。 所以查询速度快 , 增删速度较慢 。 内部实现了对数组操作过程的封装 , 然后举个添加元素add方法 , 详细阐述
一般情况下面试官感觉你说的很有逻辑 , 某个具体的点讲解又很输入 , 就不会再深究了 。
谈一下你是如何理解LinkedList集合 的也是同样套路 。
第二章 扩容类问题2.1 ArrayList 无参构造方法穿件对象后 , 调用 add方法添加 一个值进去 , 此时数组的大小是多少 , 下一次扩容前最大可用大小是多少?答:此处数组的大小是 1 , 下一次扩容前最大可用大小是 10 , 因为 ArrayList 第一次扩容时 , 是有默认值的 , 默认值是 10 , 在第一次 add 一个值进去时 , 数组的可用大小被扩容到 10 了 。
2.2 ArrayList 无参构造方法穿件对象后 , 调用 add方法连续添加 , 添加到第 11 个的时候 , 数组的大小是多少?答:这里的考查点就是扩容的公式 , 当增加到 11 的时候 , 此时我们希望数组的大小为 11 , 但实际上数组的最大容量只有 10 , 不够了就需要扩容 , 扩容的公式是:oldCapacity + (oldCapacity>> 1) , oldCapacity 表示数组现有大小 , 目前场景计算公式是:10 + 10 /2 = 15 , 然后我们发现 15 已经够用了 , 所以数组的大小会被扩容到 15 。
2.3 ArrayList 无参构造方法穿件对象后 , 调用 add方法添加 一个值进去 , 如果我使用 addAll 方法 , 一下子加入 15 个值 , 那么最终数组的大小是多少?答:第一题中我们已经计算出来数组在加入一个值后 , 实际大小是 1 , 最大可用大小是 10, 现在需要一下子加入 15 个值 , 那我们期望数组的大小值就是 16 , 此时数组最大可用大小只有 10 , 明显不够 , 需要扩容 , 扩容后的大小是:10 + 10 /2 = 15 , 这时候发现扩容后的大小仍然不到我们期望的值 16 , 这时候源码中有一种策略如下:
// newCapacity 本次扩容的大小 , minCapacity 我们期望的数组最小大小// 如果扩容后的值 < 我们的期望值 , 我们的期望值就等于本次扩容的大小if (newCapacity - minCapacity < 0)newCapacity = minCapacity;所以最终数组扩容后的大小为 16 。
2.4 现在我有一个很大的数组需要拷贝 , 原数组大小是 5k , 请问如何快速拷贝?答:因为原数组比较大 , 如果新建新数组的时候 , 不指定数组大小的话 , 就会频繁扩容 , 频繁扩容就会有大量拷贝的工作 , 造成拷贝的性能低下 , 所以回答说新建数组时 , 指定新数组的大小为 5k 即可 。
2.5 为什么说扩容会消耗性能?答:扩容底层使用的是 System.arraycopy 方法 , 会把原数组的数据全部拷贝到新数组上 , 所以性能消耗比较严重 。
2.6 源码扩容过程有什么值得借鉴的地方?答:有两点: