Skip to content

ArrayList介绍

Java ArrayList扩容策略

java.util.ArrayList是个固定大小的对象,持有一个引用指向一个数组,真正负责存储元素内容的是这个数组。 当需要扩容时,扩容的是这个数组。

  • 计算出新的容量capacity,新创建一个容量更大的数组
  • 把原数组的内容拷贝到新数组去
  • 把新数组的引用赋值到ArrayList对象的elementData字段上,完成扩容

ArrayList与Vector的主要区别

ArrayList在Java1.2时被引入,用于替换VectorVector线程安全,ArrayList不是线程安全的。 它们均为线性连续存储空间(数组实现)。 ArrayList扩容时自动计算增长值。Vector存储空间可以增长,也可以收缩。

首先看这两类都实现List接口,而List接口一共有三个实现类,分别是ArrayListVectorLinkedList。List用于存放多个元素,能够维护元素的次序,并且允许元素的重复。3个具体实现类的相关区别如下:

  • ArrayList是最常用的List实现类,内部是通过数组实现的,它允许对元素进行快速随机访问。数组的缺点是每个元素之间不能有间隔,当数组大小不满足时需要增加存储能力,就要讲已经有数组的数据复制到新的存储空间中。当从ArrayList的中间位置插入或者删除元素时,需要对数组进行复制、移动、代价比较高。因此,它适合随机查找和遍历,不适合插入和删除。
  • VectorArrayList一样,也是通过数组实现的,不同的是它支持线程的同步,即某一时刻只有一个线程能够写Vector,避免多线程同时写而引起的不一致性,但实现同步需要很高的花费,因此,访问它比访问ArrayList慢。
  • LinkedList是用链表结构存储数据的,很适合数据的动态插入和删除,随机访问和遍历速度比较慢。另外,他还提供了List接口中没有定义的方法,专门用于操作表头和表尾元素,可以当作堆栈、队列和双向队列使用。

可以用for循环直接删除ArrayList的特定元素吗?可能会出现什么问题?怎样解决?

for循环直接删除的特定元素,list中元素的下标会变。ArrayList的size会发生变化,有可能会报下标越界异常(indexOutOfRange)。

比如当你删除第1个元素后,继续根据索引访问第2个元素时,因为删除的关系后面的元素都往前移动了一位,所以实际访问的是第3个元素。

如果删除某1个特定元素,for循环中找到该元素并删除后,break跳出循环。

如果删除多个特定元素,for循环中注意执行删除操作后下标的变化,更改for循环的循环次数值。

ArrayList跟HashMap是否线程安全,如何保证线程安全

ArrayList跟HashMap都不是线程安全的。

为保证线程安全,需要给它们加上同步机制。比如使用synchronized,或是加锁。