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

  • 扩容过程中 , 有数组大小溢出的意识 , 比如要求扩容后的数组大小 , 不能小于 0 , 不能大于 Integer 的最大值 。
  • 这两点在我们平时设计和写代码时都可以借鉴 。
    第三章 删除类问题3.1 有一个 ArrayList , 数据是 2、3、3、3、4 , 中间有三个 3 , 现在我通过 for (int i=0;iList list = new ArrayList() {{add("2");add("3");add("3");add("3");add("4");}};for (int i = 0; i < list.size(); i++) {if (list.get(i).equals("3")) {list.remove(i);}}点击代码块进入预览复制代码答:不能删除干净 , 最终删除的结果是 2、3、4 , 有一个 3 删除不掉 , 原因我们看下图: 从图中我们可以看到 , 每次删除一个元素后 , 该元素后面的元素就会往前移动 , 而此时循环的 i 在不断地增长 , 最终会使每次删除 3 的后一个 3 被遗漏 , 导致删除不掉 。
    3.2 还是上面的 ArrayList 数组 , 我们通过增强 for 循环进行删除 , 可以么?答:不可以 , 会报错 。 因为增强 for 循环过程其实调用的就是迭代器的 next () 方法 , 当你调用 list#remove () 方法进行删除时 , modCount 的值会 +1 , 而这时候迭代器中的 expectedModCount 的值却没有变 , 导致在迭代器下次执行 next () 方法时 , expectedModCount != modCount 就会报 ConcurrentModificationException 的错误 。
    3.3 还是上面的数组 , 如果删除时使用 Iterator.remove () 方法可以删除么 , 为什么?答:可以的 , 因为 Iterator.remove () 方法在执行的过程中 , 会把最新的 modCount 赋值给 expectedModCount , 这样在下次循环过程中 , modCount 和 expectedModCount 两者就会相等 。
    3.4 以上三个问题对于 LinkedList 也是同样的结果么?答:是的 , 虽然 LinkedList 底层结构是双向链表 , 但对于上述三个问题 , 结果和 ArrayList 是一致的 。
    第四章 对比类问题4.1 ArrayList 和 LinkedList 有何不同?答:可以先从底层数据结构开始说起 , 然后以某一个方法为突破口深入 , 比如:最大的不同是两者底层的数据结构不同 , ArrayList 底层是数组 , LinkedList 底层是双向链表 , 两者的数据结构不同也导致了操作的 API 实现有所差异 , 拿新增实现来说 , ArrayList 会先计算并决定是否扩容 , 然后把新增的数据直接赋值到数组上 , 而 LinkedList 仅仅只需要改变插入节点和其前后节点的指向位置关系即可 。 最后说一下特点,ArrayList查询快,增删慢 LinkedList查询慢,增删快
    4.2 ArrayList 和 LinkedList 应用场景有何不同答:ArrayList 更适合于快速的查找匹配 , 不适合频繁新增删除 , 像工作中经常会对元素进行匹配查询的场景比较合适 , LinkedList 更适合于经常新增和删除 , 对查询反而很少的场景 。 比如我们后面学习的线程池和连接池,内部就可以使用LinkedList集合实现
    4.3 ArrayList 和 LinkedList 两者有没有最大容量答:ArrayList 有最大容量的 , 为 Integer 的最大值 , 大于这个值 JVM 是不会为数组分配内存空间的 , LinkedList 底层是双向链表 , 理论上可以无限大 。 但源码中 , LinkedList 实际大小用的是 int 类型 , 这也说明了 LinkedList 不能超过 Integer 的最大值 , 不然会溢出 。
    4.4 ArrayList 和 LinkedList 是如何对 null 值进行处理的答:ArrayList 允许 null 值新增 , 也允许 null 值删除 。 删除 null 值时 , 是从头开始 , 找到第一值是 null 的元素删除;LinkedList 新增删除时对 null 值没有特殊校验 , 是允许新增和删除的 。
    4.5 ArrayList 和 LinedList 是线程安全的么 , 为什么?答:当两者作为非共享变量时 , 比如说仅仅是在方法里面的局部变量时 , 是没有线程安全问题的 , 只有当两者是共享变量时 , 才会有线程安全问题 。 主要的问题点在于多线程环境下 , 所有线程任何时刻都可对数组和链表进行操作 , 这会导致值被覆盖 , 甚至混乱的情况 。


    推荐阅读