ArrayList和LinkedList
一 、ArrayList
ArrayList也就是动态数组,底层是数组实现的,其API对数组底层访问做了一层封装。add(),remove(),insert(),contains(),get(),clear(),size()
先说说数组,数组在内存中是连续存储的,它的索引速度非常快,赋值和修改元素很快捷。
因为数组是连续存储的,所以Arraylist在内存中也是连续的。
索引Arraylist的时候是要比原生数组慢的,因为你要用get方法,也就是函数调用,而数组就是直接[]访问,相当于直接操作内存地址,速度肯定比函数调用快。
但是数组有不足,在数组的两个数据中间插入数据是很麻烦的,并且在声明数组的时候我们必须同时指定数组的长度,数组的长度过长,会造成内存浪费,数组的长度过短会造成数据的溢出错误。
所以就有了Arraylist来有取舍的优化,ArrayList和Array各有优点和用处。
Array和ArrayList的一些不同点:
- 1、Array可以包含基本类型和对象类型,ArrayList只能包含对象类型。
- 2、Array大小是固定的,ArrayList的大小是动态变化的。
- 3、ArrayList提供了更多的方法和特性,比如:add(),removeAll(),iterator()等等。所以ArrayList的可操作性就更强了,可以对数据方便的添加、插入和删除。(其实它的插入、删除的效率不高,LinkedList的插入、删除高)
- 4、ArrayList还存在不安全类型和装箱和拆箱的缺点,可以用泛型解决这些缺点。ArrayList还是线程不安全的,因为它里面的方法不能保证操作的原子性。
- 5、ArrayList继承了AbstractList,实现了List、RandomAccess[随机访问], Cloneable[可克隆], java.io.Serializable[序列化]。
扩展:序列化是指:将对象转换成以字节序列的形式来表示,以便用于持久化和传输。序列化id相当于给一个类对象一个版本id,修改这个类的属性之后就要改变序列化id。
二、LinkedList:基于双向链表,分散存储,适合插入、删除,不适合查询
// 迭代器遍历
Iterator ite = link.iterator(); while (ite.hasNext()) { System.out.println(ite.next()); }
- ArrayLis、Vector、LinkedList比较
ArrayList:底层数组式连续内存储存。适合随机访问,查询,不适合插入删除,会消耗大量时间。线程不同步(线程不安全),ArrayList扩容后的容量是之前的1.5倍,然后把之前的数据拷贝到新建的数组中,效率高。
Vector:和ArrayList一样使用数组方式存储数据。适合随机访问,查询,不适合插入删除,会消耗大量时间。线程安全,内部加锁。扩容后是之前的2倍。效率没有其他两个高。
LinkedList:底层双向链表的形式存储数据,对增删元素有很高的效率,查询效率低。线程不安全。
- 有一个很大的数组需要拷贝,原数组大小5k,请问如何快速扩容?
答:因为数组很大,新建数组的时候,不指定数组的大小,会频繁扩容,频繁扩容会有大量的拷贝的工作,造成拷贝的性能低下。所有新建数组的时候,指定数组的大小为5k即可。
- 为什么说扩容会消耗性能?
动态数组扩容底层使用的是System.Arraycopy方法,会把原数组的数据全部拷贝到新数组上,就很消耗性能。