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?
答:加锁操作是非常耗时的