ArrayList相关面试题

ArrayList与LinkedList的区别

  1. 线程安全:二者都不保证线程安全。若是须要线程安全的可使用:

线程安全解决办法 :
方法1: Collections.synchronizedList(new LinkedList())
方法2: LinkedList和ArrayList换成线程安全的集合,如CopyOnWriteArrayList,ConcurrentLinkedQueue…
方法3:Vector(内部主要使用synchronized关键字实现同步)java

  1. 底层数据结构:ArrayList底层数据结构是Object数组。LinkedList的是双向链表(1.6及以前使用的是循环链表)。
  2. 插入和删除操做的时间复杂度不一样:
    ArrayList的底层是数组存储。插入和删除元素的时间复杂度受元素位置的影响。若是没有指定位置默认加入到链表尾部,为O(1),若是是指定加入到 i 位置则为O(n-i)
    LinkedList底层是链表,在插入和删除元素时间复杂度不受元素位置影响近似于O(1),若是插入到指定位置是O(n)。
  3. 是否支持快速访问:LinkedList不支持,ArrayList支持,由于底层是数组。
  4. 内存空间占用状况:ArrayList的内存占用在相同状况下小于LinkedList。ArrayList的内存占用主要在于尾部没有存储数据时。而LinkedList的内存每一个元素须要额外存储前驱结点和后继结点。

RandomAccess接口

  1. RandomAccess接口什么也没定义。只是做为一个标识符。标识实现这个接口的类具备随机访问的功能。
  2. 如:在binarySearch()方法中,他被用来判断传入的list是否RandomAccess实例,若是是,调用indexedBinarySearch()方法,若是不是,那么调用iteratorBinarySearch()方法。
  3. 实现了RandomAccess的list,优先遍历的方式是for循环,而后再是foreach(foreach底层是iterator实现的)。没有实现的优先选择iterator。
  4. 对于ArrayList就实现了该接口而LinkedList没有实现。由于ArrayList的底层是数组,数组自然支持随机访问,时间复杂度为O(1)。而LinkedList底层是链表不能随机访问,只能从头指针处进行遍历。

ArrayList与Vector区别,为何用ArrayList取代Vector

  1. Vector类的全部方法都是同步的,若是仅仅是一个线程去操做的话,就会消耗不少的时间在同步操做上。
  2. ArrayList不是同步的,因此在不须要保证线程安全的状况下使用ArrayList更好。

ArrayList的扩容机制

ArrayList有三种构造方法
第一种:不含参数的默认构造方法
public ArrayList()
第二种:带初始容量参数的构造函数(用户可本身指定容量)
public ArrayList(int initialCapacity)
第三种:构造包含指定collection元素的列表。
public ArrayList(Collection<? extends E> c)git

  1. 在使用无参构造的时候,会初始化一个空数组。当真正的添加元素的时候才给数组真正的分配容量。即便用add(E e)方法时,才会将数组容量扩充为10.

具体过程: 当咱们要 add 进第1个元素到 ArrayList 时,elementData.length 为0 (由于仍是一个空的 list),由于执行了 ensureCapacityInternal() 方法 ,因此 minCapacity 此时为10。此时,minCapacity - elementData.length > 0 成立,因此会进入 grow(minCapacity) 方法。
当add第2个元素时,minCapacity 为2,此时e lementData.length(容量)在添加第一个元素后扩容成 10 了。此时,minCapacity - elementData.length > 0 不成立,因此不会进入 (执行)grow(minCapacity) 方法。
添加第三、4···到第10个元素时,依然不会执行grow方法,数组容量都为10。
直到添加第11个元素,minCapacity(为11)比elementData.length(为10)要大。进入grow方法进行扩容。
ArrayList 每次扩容以后容量都会变为原来的 1.5 倍左右(oldCapacity为偶数就是1.5倍,不然是1.5倍左右)! 奇偶不一样,好比 :10+10/2 = 15, 33+33/2=49。若是是奇数的话会丢掉小数.github

最好在 add 大量元素以前用 ensureCapacity 方法,以减小增量从新分配的次数
更详细的源码解读web

参考:JavaGuide面试