List接口
- 存储的数据特点:存储序的、可重复的数据。
- 常用方法:(记住)
- 增:add(Object obj)
- 删:remove(int index) / remove(Object obj)
- 改:set(int index, Object ele)
- 查:get(int index)
- 插:add(int index, Object ele)
- 长度:size()
- 遍历:① Iterator迭代器方式
② 增强for循环
③ 普通的循环
JDK API中List接口的实现类常用的有:ArrayList、LinkedList和Vector
ArrayList
本质上,ArrayList是对象引用的一个”变长”数组
1 源码分析(重要部分),
JDK1.7:ArrayList像饿汉式,直接创建一个初始容量为10的数组
JDK1.8:ArrayList像懒汉式,一开始创建一个长度为0的数组,当添加第一个元素时再创建一个始容量为10的数组
JDK1.7 :
- ArrayList list = new ArrayList();//底层创建了长度是10的Object[]数组elementData
- 添加元素时,如果此次的添加导致底层elementData数组容量不够,则扩容。默认情况下,扩容为原来的容量的1.5倍,同时需要将原有数组中的数据复制到新的数组中。
- 结论:建议开发中使用带参的构造器:ArrayList list = new ArrayList(int capacity)
JDK 8中ArrayList的变化:
- ArrayList list = new ArrayList();//底层Object[] elementData初始化为{}.并没创建长度为10的数组
- list.add(123);//第一次调用add()时,底层才创建了长度10的数组,并将数据123添加到elementData[0]
- 后续的添加和扩容操作与jdk 7 无异。
LinkedList
LinkedList:双向链表,内部没有声明数组,而是定义了Node类型的first和last,用于记录首末元素。同时,定义内部类Node,作为LinkedList中保存数据的基本结构。Node除了保存数据,还定义了两个变量,prev变量记录前一个元素的位置,next变量记录下一个元素的位置
- 对于频繁的插入或删除元素的操作,建议使用LinkedList类,效率较高
Vector
- Vector 是一个古老的集合,JDK1.0就有了。大多数操作与ArrayList
相同,区别之处在于Vector是线程安全的。 - 在各种list中,最好把ArrayList作为缺省选择。当插入、删除频繁时,
使用LinkedList;Vector总是比ArrayList慢,所以尽量避免使用。 - jdk7和jdk8中通过Vector()构造器创建对象时,底层都创建了长度为10的数组。在扩容方面,默认扩容为原来的数组长度的2倍。
面试题
1 请问ArrayList/LinkedList/Vector的异同?谈谈你的理解?ArrayList底层
是什么?扩容机制?Vector和ArrayList的最大区别?
- ArrayList和LinkedList的异同
二者都线程不安全,相对线程安全的Vector,执行效率高。
此外,ArrayList是实现了基于动态数组的数据结构,LinkedList基于链表的数据结构。对于随机访问get和set,ArrayList觉得优于LinkedList,因LinkedList要移动指针。对于新增和删除操作add(特指插入)和remove,LinkedList比较占优势,因为ArrayList要移动数据。 - ArrayList和Vector的区别
Vector和ArrayList几乎是完全相同的,唯一的区别在于Vector是同步类(synchronized),属于强同步类。因此开销就比ArrayList要大,访问要慢。正常情况下,大多数的Java程序员使用ArrayList而不是Vector,因为同步完全可以由程序员自己来控制。Vector每次扩容请求其大小的2倍空间,而ArrayList是1.5倍。Vector还有一个子类Stack。