List集合
List集合框架
* |----Collection接口:单列集合,用来存储一个一个的对象
* |----List接口:存储有序的、可重复的数据。 -->“动态”数组,替换原有的数组
* |----ArrayList:作为List接口的主要实现类;线程不安全的,效率高;底层使用Object[] elementData存储
* |----LinkedList:线程不安全对于频繁的插入、删除操作,使用此类效率比ArrayList高;底层使用双向链表存储
* |----Vector:作为List接口的古老实现类;线程安全的,效率低;底层使用Object[] elementData存储
List接口当中的常用api方法
//除了Collection接口中的方法,还增加了一些根据元素索引来操作集合的特定方法
void add(int index,E element); 指定的元素添加到集合中的指定位置
boolean addAll(int index, Collection<? extends E> c) 将指定集合中的所有元素插入到此列表中的指定位置(可选操作)。
E get(int index); 根据指定的索引获取对应位置上的元素
int indexOf(Object o) 返回此列表中指定元素的第一次出现的索引,如果此列表不包含元素,则返回-1。
int lastIndexOf(Object o) 返回此列表中指定元素的最后一次出现的索引,如果此列表不包含元素,则返回-1。
E remove(int index); 通过索引删除对位置上的元素
E set(int index ,E element); 在指定的位置上替换成给定的元素,并且放回
default void sort(Comparator<? super E> c) 根据指定的Comparator引发的顺序排列此列表。
List<E> subList(int fromIndex, int toIndex) 返回指定的 fromIndex (含)和 toIndex之间的列表部分的视图。
注意事项
- List接口中带索引的方法(特有的)
- 操作带索引的方法的时候,一定要防止索引越界异常
- foreach循环迭代数组/集合元素时,不能改变数组/集合元素的值,因此,不要对foreach的循环变量进行赋值
- foreach可以改变对象的值,但不能删除或添加对象.
list集合特点
- 有序,存储和取出元素顺序一致
- 可重复:存储的元素可以重复
- 元素以线性方式存储
Arraylist
- java.util 包下下的
底层是Object数组实现的,特点是查询速度快,增加删除慢,线程不安全,
jdk1.8 时,使用无参创建对象是默认容量时 10,长度不够时,自动增长0.5倍,就是原来数组的 .15倍
ArrayList的源码分析
-
jdk 7情况下
* ArrayList list = new ArrayList();//底层创建了长度是 10的Object[]数组elementData * list.add(123);//elementData[0] = new Integer(123); * ... * list.add(11);//如果此次的添加导致底层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集合
-
java.util.LinkedList 集合数据存储采用的是链表结构。方便元素的添加和删除操作。
-
LinkedList是一个双向链表,特点,增删块,查询慢,线程不安全,在LinkedList集合当中,封装了大量关于首节点和尾节点的元素操作方法(开发中常用)
public void addFirst(E e);将指定的元素插入到首节点位置 public void addLast(E e); 将指定的元素插入到尾节点的位置上 public E gerFirst(); 获取首节点元素 public E getLast(); 获取尾节点元素 public E removeFirst(); 删除首节点的元素 public E removeLast(); 删除尾节点元素 public E pop(); 从链表结构堆栈中弹出一个元素(首节点) public void push(E e); 将元素推入到此列表所表示的堆栈当中(首节点) public boolean isEmpty(); 如果此列表不包含任何元素,则返回true
LinkedList的源码分析:
* LinkedList list = new LinkedList(); 内部声明了Node类型的first和last属性,默认值为null
* list.add(123);//将123封装到Node中,创建了Node对象。
*
* 其中,Node定义为:体现了LinkedList的双向链表的说法
* private static class Node<E> {
E item;
Node<E> next;
Node<E> prev;
Node(Node<E> prev, E element, Node<E> next) {
this.item = element;
this.next = next;
this.prev = prev;
}
}
LinkedList集合的特点
- 底层是一个链表结构,查询慢,增删快
- 里面包含了大量的首位节点操作的方法
- 允许所有的元素(包括null)
- 此实现不是同步的。如果多个线程同时访问一个连接表,而其中至少一个线程从结构上修改了该列表,则必须保持外部同步
- 元素有序的。
Vector的源码分析
- Vector 是一个古老的集合, jdk1.0 就有了,大多数操作于 Arraylist相同,区别之处在于Vector是线程安全的
- 在各种 list中,最好把 Arraylist作为缺省选择.但插入,删除频繁时,使用 LinkedList;Vector总是比ArrayList慢,所以尽量避免使用.
方法
void addElement(Object obj)
void insertElementAt(Object obj,int index)
void setElementAt(Object obj,int index)
void removeElement(Object obj)
void removeAllElements()
扩容机制
* jdk7和jdk8中通过Vector()构造器创建对象时,底层都创建了长度为10的数组。
* 在扩容方面,默认扩容为原来的数组长度的2倍。
面试题:ArrayList、LinkedList、Vector三者的异同?
- 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