Java集合精选常见面试题( 三 )

get(int index)方法) 。

  • 内存空间占用: ArrayList 的空间浪费主要体现在 list 列表的结尾会预留一定的容量空间,而 LinkedList 的空间花费则体现在它的每一个元素都需要消耗比 ArrayList 更多的空间(因为要存放直接后继和直接前驱以及数据)
  • LinkedList
    1. 基于双向链表,无需连续内存
    2. 随机访问慢(要沿着链表遍历)
    3. 头尾插入删除性能高,中间元素慢
    4. 占用内存多
    ArrayList
    1. 基于数组,需要连续内存
    2. 随机访问快(指根据下标访问)
    3. 尾部插入、删除性能可以,其它部分插入、删除都会移动数据,因此性能会低
    4. 可以利用 cpu 缓存,局部性原理
    补充内容:双向链表和双向循环链表双向链表: 包含两个指针,一个 prev 指向前一个节点,一个 next 指向后一个节点 。
    另外推荐一篇把双向链表讲清楚的文章:https://juejin.cn/post/6844903648154271757(opens new window)

    Java集合精选常见面试题

    文章插图
    双向循环链表: 最后一个节点的 next 指向 head,而 head 的 prev 指向最后一个节点,构成一个环
    Java集合精选常见面试题

    文章插图
    补充内容:RandomAccess 接口public interface RandomAccess {}查看源码我们发现实际上 RandomAccess 接口中什么都没有定义 。所以,在我看来 RandomAccess 接口不过是一个标识罢了 。标识什么? 标识实现这个接口的类具有随机访问功能 。
    binarySearch() 方法中,它要判断传入的 list 是否 RamdomAccess 的实例,如果是,调用indexedBinarySearch()方法,如果不是,那么调用iteratorBinarySearch()方法
    public static <T>int binarySearch(List<? extends Comparable<? super T>> list,T key) {if (list instanceof RandomAccess || list.size()<BINARYSEARCH_THRESHOLD)return Collections.indexedBinarySearch(list,key);elsereturn Collections.iteratorBinarySearch(list,key);}ArrayList 实现了 RandomAccess 接口,而 LinkedList 没有实现 。为什么呢?我觉得还是和底层数据结构有关!ArrayList 底层是数组,而 LinkedList 底层是链表 。数组天然支持随机访问,时间复杂度为 O(1),所以称为快速随机访问 。链表需要遍历到特定位置才能访问特定位置的元素,时间复杂度为 O(n),所以不支持快速随机访问 。,ArrayList 实现了 RandomAccess 接口,就表明了他具有快速随机访问功能 。RandomAccess 接口只是标识,并不是说 ArrayList 实现 RandomAccess 接口才具有快速随机访问功能的
    3. 说一说 ArrayList 的扩容机制吧ArrayList核心源码详见这篇文章:通过源码一步一步分析 ArrayList 扩容机制
    先从 ArrayList 的构造函数说起(JDK8)ArrayList 有三种方式来初始化,构造方法源码如下:
    /*** 默认初始容量大小10*/private static final int DEFAULT_CAPACITY = 10;private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = https://www.huyubaike.com/biancheng/{};/***默认构造函数,使用初始容量10构造一个空列表(无参数构造)*/public ArrayList() {this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;}/*** 带初始容量参数的构造函数 。(用户自己指定容量)*/public ArrayList(int initialCapacity) {if (initialCapacity > 0) {//初始容量大于0//创建initialCapacity大小的数组this.elementData = new Object[initialCapacity];} else if (initialCapacity == 0) {//初始容量等于0//创建空数组this.elementData = EMPTY_ELEMENTDATA;} else {//初始容量小于0,抛出异常throw new IllegalArgumentException("Illegal Capacity: "+initialCapacity);}}/***构造包含指定collection元素的列表,这些元素利用该集合的迭代器按顺序返回*如果指定的集合为null,throws NullPointerException 。*/public ArrayList(Collection<? extends E> c) {elementData = https://www.huyubaike.com/biancheng/c.toArray();if ((size = elementData.length) != 0) {// c.toArray might (incorrectly) not return Object[] (see 6260652)if (elementData.getClass() != Object[].class)elementData = Arrays.copyOf(elementData,size,Object[].class);} else {// replace with empty array.this.elementData = EMPTY_ELEMENTDATA;}}

    经验总结扩展阅读