基础

数组列表,主要用来装在数据。
和它类似的还有LinkedList,ArrayList查找和访问元素的速度较快,但是新增、删除比较慢

为什么线程不安全还在使用?

大多数场景,都是查询,不太设计频繁的增删。

底层是数组,数组是定长的,不断添加元素不会有问题吗?

  • ArrayList可以通过构造方法初始化的时候初始化底层数组的大小
  • 默认初始化一个数组容量为0的空数组,只有真正add的时候,才分配默认DEFAULT_CAPACITY = 10的初始容量。

    扩容机制

    一个长度为10的数组,新增一个元素,发现已经满了
  1. 重新定义一个长度10+ 10/2的数组,也就是新增一个长度为15的数组
  2. 把原来数组的数据,原封不动的复制到新的数组中,这个时候再把原数组的地址指向新数组,这样ArrayList就完成了一次改头换面。

    为什么初始长度是10?

    好像是调研之后,10这个长度最常用最有效率。没啥其他原因,8、12也没啥。10比较圆满

    ArrayList增删元素怎么做的?为什么慢?

    新增元素

    新增元素的时候,有根据index新增的,也有直接新增的。在这之前先检验长度的判断,如果长度不够,就需要扩容。
    image.png
    1.8 底层采用了位运算。
    image.png
    如果是指定位置新增,会先复制一个数组,然后再把元素放进去,后面的所有元素都得复制,如果再涉及扩容,就更慢了。

    删除元素

    删除元素一定慢吗?

看删除的元素离数组末端有多远。

删除怎么实现的?

和新增类似,还是在cpoy一个数组。

ArrayList(int initialCapacity)会初始化数组大小吗?

image.png
会。但是list.size() == 0

数组初始化了,但是list没有,size没变

demo

  1. public static void main(String[] args) {
  2. List<String> list = new ArrayList<>(10);
  3. System.out.println(list.size());
  4. list.add(5, "6");
  5. }

image.png

ArrayList适合做队列吗?

队列一般都是先进先出(FIFO), 如果用ArrayList做队列,就需要数组尾部追加数据,数组头部删除数组,反过来也可以。但是任何一个操作都会涉及数组的数据搬迁,比较耗费性能。 结论:不适合。

数组适合做队列吗?

适合。比如ArrayBlockingQueue,内部就是一个环形队列,是一个定长队列,内部就是用一个定长数组来实现的。

简单来说就是用两个偏移量来标记数组的读位置和写位置,如果超过长度就折回出数组开头,前提是他们是定长数组。

ArrayList和LinkedList遍历性能比较?

ArrayList比LinkedList快很多。ArrayList遍历的最大优势在于内存的连续性,CPU的内部缓存结构会缓存连续的内存片段,大幅度降低读取内存的开销。