list接口特点
是Collection接口的子接口,也是最常用的接口。此接口对Collection接口进行了大量的扩充,
里面的内容是1)允许重复 2)允许为NULL 3)并且有序(插入的顺序)。
List接口常用的实现类有3个:ArrayList、LinkedList、Vector。
1、ArrayList:
ArrayList是一种变长的集合类,基于定长数组实现
继承接口:
ArrayList:public class ArrayList<E> extends AbstractList<E>
implements List<E>, RandomAccess, Cloneable, java.io.Serializable
1)实现List接口:是Collection接口的子接口,也是最常用的接口。此接口对Collection接口进行了大量的扩充, 里面的内容是允许重复允许为NULL的并且有序(插入的顺序)。
2)Cloneable接口:Cloneable是标记型的接口,它们内部都没有方法和属性,实现 Cloneable来表示该对象能被克隆, 能使用Object.clone()方法。如果没有实现 Cloneable的类对象调用clone()就会抛出CloneNotSupportedException。
3)Serializable接口:public interface Serializable类通过实现 java.io.Serializable 接口以启用其序列化功能。
构造器
初始化数组(无参初始化为空数组,有参初始化为initialCapacity)
public ArrayList(int initialCapacity) {
super();
if (initialCapacity < 0)
throw new IllegalArgumentException("Illegal Capacity: "+
initialCapacity);
this.elementData = new Object[initialCapacity];
}
/**
* Constructs an empty list with an initial capacity of ten.
*/
public ArrayList() {
super();
this.elementData = EMPTY_ELEMENTDATA;
}
增删改查
增
判断是否需要扩容,扩容为原来的1.5倍
public boolean add(E e)插入元素,尾插
public void add(int index, E element)插入元素到指定索引
删
public E remove(int index)删除指定位置的元素
public boolean remove(Object o)删除指定值的元素
改
public E set(int index, E element)修改指定位置的元素的值为element
查
public E get(int index)查询指定索引的元素
迭代器
private class Itr implements Iterator
迭代器中的主要方法:
next(); 返回下一个元素
hasnext(); 是否有下一个元素?
remove();从基础集合中移除此迭代器返回的最后一个元素。
遍历
遍历有四种方式
1、 for循环
2、 foreach
3、 iterator.hasNext()
4、 ListIterator.hasNext()(是list接口下特有的)
ListIteration.hasPrevious()从后往前
快速失败机制
ModCount++控制
ArrayList 迭代器中的方法都是均具有快速失败的特性,当遇到并发修改的情况时,迭代器会快速失败,以避免程序在将来不确定的时间里出现不确定的行为。
2、Vector
实现接口
public class Vector<E>
extends AbstractList<E>
implements List<E>, RandomAccess, Cloneable, java.io.Serializable
和ArrayList相同
构造器
(与ArrayList的区别)
public Vector(int initialCapacity, int capacityIncrement) {
super();
if (initialCapacity < 0)
throw new IllegalArgumentException("Illegal Capacity: "+
initialCapacity);
this.elementData = new Object[initialCapacity];
this.capacityIncrement = capacityIncrement;
}
这两个参数分别是,初始化大小和,增量,也就是指定了扩容方式。
public Vector(int initialCapacity) {
this(initialCapacity, 0);
}
底层调用双参构造器,增量默认为0。
public Vector() {
this(10);
}
初始化数组,默认大小为10。
增删改查,遍历方法,迭代器与ArrayList相同,但是方法都用了Synchronized 来修饰,是线程安全
扩容方式有区别,如果需要增量没有设置,默认两倍扩容,如果设置了增量,那么每一次扩容一个增量的大小。
3、LinkedList:
LinkedList基于双向链表实现
实现接口
linkedList :public class LinkedList<E>
extends AbstractSequentialList<E>
implements List<E>, Deque<E>, Cloneable, java.io.Serializable
1)实现List接口:是Collection接口的子接口,也是最常用的接口。此接口对Collection接口进行了大量的扩充, 里面的内容是允许重复允许为NULL的并且有序(插入的顺序)。
2)Deque实现Queue接口:具有队列先入先出的特点。此接口的子类可以实现队列操作。双端队列
3)Cloneable接口:Cloneable是标记型的接口,它们内部都没有方法和属性,实现 Cloneable来表示该对象能被克隆,能使用Object.clone()方法。如果没有实现 Cloneable的类对象调用clone()就会抛出CloneNotSupportedException。
4)Serializable接口:public interface Serializable类通过实现 java.io.Serializable 接口以启用其序列化功能。
构造器
public LinkedList() {
}
/**
* Constructs a list containing the elements of the specified
* collection, in the order they are returned by the collection's
* iterator.
*
* @param c the collection whose elements are to be placed into this list
* @throws NullPointerException if the specified collection is null
*/
public LinkedList(Collection<? extends E> c) {
this();
addAll(c);
}
无参构造:链表的添加不需要开辟空间
有参构造:将集合传入
增删改查
增
public boolean add(E e)增加指定元素(尾插)
public void add(int index, E element)增加元素在指定索引下
public void addFirst(E e)头插
public void push(E e)当用链式结构实现栈时,进栈
删
public E removeFirst()头删
public boolean remove(Object o)删除链表中的指定元素
public E remove(int index)删除指定位置的元素
public E pop()当用链式结构实现栈时,出栈操作
改
public E set(int index, E element)修改index索引下的值为element,并返回原来的值
查
public E peekFirst()查询第一个
public E peekLast()查询最后一个
public E get(int index)查询指定索引的元素
队列的相关操作
public boolean offerFirst(E e) 在队首增加e
public boolean offerLast(E e)在队尾增加e
public E peekFirst()获取队首元素
public E peeklast()获取队尾元素
public E pollFirst()删除队首元素并返回
public E polllast()删除队尾元素并返回
迭代器
private class ListItr implements ListIterator
迭代器中的主要方法:
next(); 返回下一个元素
hasnext(); 是否有下一个元素?
remove();从基础集合中移除此迭代器返回的最后一个元素。
遍历方式
遍历有四种方式
1、 for循环
2、 foreach
3、 iterator.hasNext()
4、 ListIterator.hasNext()(是list接口下特有的)
ListIteration.hasPrevious()从后往前
与ArrayList相同同样具备快速失败机制。并且非线程安全
ArrayList 和LinkedList 的异同
1)从继承的接口来看:
ArrayList: List, RandomAccess, Cloneable, java.io.Serializable
LinkedList:implements List, Deque, Cloneable, java.io.Serializable
ArrayList比 LinkedList多实现一个RandomAccess,用来表明其支持快速(通常是固定时间)随机访问。
LinkedList比ArrayList多实现一个Deque,具有队列先入先出的特点。此接口的子类可以实现队列操作。
2)底层实现上来看
ArrayList底层用数组来实现,LinkedList底层用双链表来实现。
那么ArrayList的和LinkedList的对比就会退化为数组和链表的区别。
数组随机访问一个元素的时间复杂度是O(1)。
链表的随机访问一个元素的时间复杂度是O(n)。
因为数组的访问只需要给定下标,就可以立马访问,而链表需要遍历,遍历的次数即为下标值。
ArrayList 的 get() ,set()方法相对于LinkedList效率要高,ArrayList的查询以及获取元素,效率更高
数组随机添加/删除一个元素的时间复杂度是O(n)。
链表随机添加/删除一个元素的时间复杂度是O(1)。
因为数组随机添加一个元素,指定下标的元素以及后面的所有元素,都需要向后移动,开销很大,而链表只需要将指定位置下标的上一个的节点确定,改变引用即可,开销很小。linkedList的增删效率更高
3)使用场景
根据特点来分析使用场景
如果需要增删频繁,则使用LinkedList;
如果需要查询操作频繁,则使用ArrayList;
ArrayList 和Vector的异同
1)从继承的接口来看:
实现的接口相同,特点相同
2)底层实现上来看
都是数组实现,调用方法没有区别
3)从源码上来看
a:
ArrayList 的初始数组大小为空
Vector的初始数组大小为10
b:
扩容方法:Vector更合理
ArrayList 以1.5倍扩容,如果目前元素时1000,再增加1个,则要1.5倍扩容,会造成499个空间的浪费。
Vector默认2倍扩容,如果增长因子大于零,则扩容增长因子个大小。
c:
线程安全问题:
Vector:方法都用了Synchronized 来修饰,是线程安全, 缺点:效率低,因为加在方法上(同HashTable)
ArrayList :没有加锁是线程不安全的
4)使用场景
如果需要考虑线程安全问题,则选择Vector
如果不考虑线程安全问题,则选择ArrayList
(为什么不考虑线程安全问题时不使用Vector?
答:加锁操作是非常耗时的)