1.集合的引入
集合之前保存多个数据,只能使用数组进行存储,而数组存在一些不足:
长度开始时就必须指定,而且一旦指定,就不能进行更改;
存储的数据必须是同一类型;
使用数组进行增加/删除元素的代码比较麻烦;
集合的优势:
可以动态保存任意多个对象,使用比较方便;
提供了一系列方便的操作对象的方法:add、remove、set、get等;
使用集合添加、删除新元素的示意代码更简洁了。
2.集合的框架体系
![](https://i-blog.csdnimg.cn/blog_migrate/dbfcbfab58a64402bfae4fc6e185e4b2.png)
Collection接口有两个重要的子接口List、Set,他们的实现子类都是单列集合;本文主要使用ArrayList子类对List接口进行介绍。
3.List接口的特性
(1)List接口是Collection接口的子接口:
List集合类中元素有序(即添加顺序和取出顺序一致)、且可重复(可存入null);
List集合中的每个元素都有其对应的顺序索引,即支持索引;
List容器中的元素都对应一个整数型的序号记载其在容器中的位置,可以根
据序号存取容器中的元素;
JDK API中List接口的实现类(常用的): ArrayList、LinkedList和Vector。
(2)List接口的常用方法: void add(int index, Object ele):在 index 位置插入 ele 元素 boolean addAll(int index, Collection eles):从 index 位置开始将 eles 中的所有元素添加进来 Object get(int index):获取指定 index 位置的元素 int indexOf(Object obj):返回 obj 在集合中首次出现的位置 int lastIndexOf(Object obj):返回 obj 在当前集合中末次出现的位置 Object remove(int index):移除指定 index 位置的元素,并返回此元素 Object set(int index, Object ele):设置指定 index 位置的元素为 ele , 相当于是替换. list.set(1, "玛丽"); List subList(int fromIndex, int toIndex):返回从 fromIndex 到 toIndex 位置的子集合 注意返回的子集合 fromIndex<= subList < toIndex
4. List集合的三种遍历方式
1). 使用迭代器进行遍历,List集合实现了Iterable接口,因此可以使用迭代器。
//示例代码 Iterator iterator = list.iterator(); while (iterator.hasNext()) { Object obj = iterator.next(); System.out.println(obj); }
2). 使用增强for循环进行遍历,foreach循环。(底层也是迭代器实现)
for (Object o : list) { System.out.println("o=" + o); }
3). 使用普通for循环进行遍历,利用List支持索引的特性。
for (int i = 0; i < list.size(); i ++){ System.out.println("对象=" + list.get(i);
}
5. List底层结构和源码分析
ArrayList与Vector的对比:
1) ArrayList中维护了一个Object类型的数组elementData. [debug看源码]
transient Object[] elementData; //transient表示瞬间,短暂的,表示该属性不会被序列号
2)当创建ArrayList对象时,如果使用的是无参构造器,则初始elementData容量为0,第1次添加,则扩容elementData为10,如需要再次扩容,则扩容elementData为1.5倍。
3)如果使用的是指定大小的构造器,则初始elementData容量为指定大小,如果需要扩容,则直接扩容elementData为1.5倍。
4)ArrayList基本等同于Vector,除了ArrayList是线程不安全(执行效率高)看源码.在多线程情况下,不建议使用ArrayList。Vector是线程同步的,即线程安全,因为Vector类的操作方法带有synchronized。
![](https://i-blog.csdnimg.cn/blog_migrate/2f05a826903e96dfe3d727e350766812.png)
ArrayList与LinkedList的对比:
1)LinkedList底层实现了双向链表和双端队列特点
2)可以添加任意元素(元素可以重复),包括null
3)线程不安全,没有实现同步
LinkedList底层操作机制:
1) LinkedList底层维护了一个双向链表;
2) LinkedList中维护了两个属性first和last分别指向首节点和尾节点;
3)每个节点(Node对象),里面又维护了prev.next、item三个属性,其中通过prev指向前一个,通过next指向后一个节点。最终实现双向链表;
4)所以LinkedList的元素的添加和删除,不是通过数组完成的,相对来说效率较高。
如何选择ArrayList和LinkedList:
1)如果我们改查的操作多,选择ArrayList;
2)如果我们增删的操作多,选择LinkedList;
3)一般来说,在程序中,80%-90%都是查询,因此大部分情况下会选择ArrayList;
4)在一个项目中,根据业务灵活选择,也可能这样,一个模块使用的是ArrayList,另
外一个模块是LinkedList,也就是说,要根据业务来进行选择。
![](https://i-blog.csdnimg.cn/blog_migrate/0780939a9f8d2cfc303fbd692349d548.png)