ArrayList 是List<T> 下,java的自实现类之一,我们可以将其看作是能够自动增长容量的数组。 属于线程非安全的类型,多线程环境下可以考虑用Collections.synchronizedList(List l)函数返回一个线程安全的ArrayList类,也可以使用concurrent并发包下的CopyOnWriteArrayList类,还可以考虑使用Vector这个类型。
1.ArrayList底层采用数组实现,当使用不带参数的构造方法生成ArrayList对象时,实际上会在底层生成一个长度为10的Object类型数组
2.如果增加的元素个数超过了10个,那么ArrayList底层会新生成一个数组,长度为原数组的1.5倍+1,然后将原数组的内容复制到新数组当中,并且后续增加的内容都会放到新数组当中。当新数组无法容纳增加的元素时,重复该过程。
数据整体移动是非常耗费性能的操作,所以我们尽可能的预先估算出数组的大小, 构造一个指定初始容量的空列表:
public ArrayList(int initialCapacity)
这样可以减少数据复制移动的次数
3.对于ArrayList元素的删除操作,需要将被删除元素的后续元素向前移动,代价比较高。
4.集合当中只能放置对象的引用,无法放置原生数据类型,我们需要使用原生数据类型的包装类才能加入到集合当中。
5.集合当中放置的都是Object类型,因此取出来的也是Object类型,那么必须要使用强制类型转换将其转换为真正的类型(放置进去的类型)
如果将值类型数据放进ArrayList 会伴随有装箱操作, 获得的时候可能还会有拆箱操作, 如果数据量大的话是非常消耗性能的
这时候我们可以用ArrayList<T>, 指定泛型省去了拆箱装箱的损耗
因为ArrayList的底层是数组实现, 因而适合随机查找, 如果频繁的使用删除和中间插入可以使用底层为链表实现的LinkedList,二者的区别大概就是数组与链表的区别:
ArrayList 是线性表(数组)
get() 直接读取第几个下标,复杂度 O(1)
add(E) 添加元素,直接在后面添加,复杂度O(1)
add(index, E) 添加元素,在第几个元素后面插入,后面的元素需要向后移动,复杂度O(n)
remove()删除元素,后面的元素需要逐个移动,复杂度O(n)
LinkedList 是链表的操作
get() 获取第几个元素,依次遍历,复杂度O(n)
add(E) 添加到末尾,复杂度O(1)
add(index, E) 添加第几个元素后,需要先查找到第几个元素,直接指针指向操作,复杂度O(n)
remove()删除元素,直接指针指向操作,复杂度O(1)
参考如下博主