java -- List总结

java -- List总结

概括

  1. List 是一个接口,它继承于Collection的接口。它代表着有序的队列。

  2. AbstractList 是一个抽象类,它继承于AbstractCollection。AbstractList实现List接口中除size()、get(int location)之外的函数。

  3. AbstractSequentialList 是一个抽象类,它继承于AbstractList。AbstractSequentialList 实现了“链表中,根据index索引值操作链表的全部函数”。

  4. ArrayList, LinkedList, Vector, Stack是List的4个实现类。

  • ArrayList 是一个数组队列,相当于动态数组。它由数组实现,随机访问效率高,随机插入、随机删除效率低。
  • LinkedList 是一个双向链表。它也可以被当作堆栈、队列或双端队列进行操作。LinkedList随机访问效率低,但随机插入、随机删除效率高。
  • Vector 是矢量队列,和ArrayList一样,它也是一个动态数组,由数组实现。但是ArrayList是非线程安全的,而Vector是线程安全的。
  • Stack 是栈,它继承于Vector。它的特性是:先进后出(FILO, First In Last Out)。

应用场景

    如果涉及到“栈”、“队列”、“链表”等操作,应该考虑用List,具体的选择哪个List,根据下面的标准来取舍。

  • 对于需要快速插入,删除元素,应该使用LinkedList。
  • 对于需要快速随机访问元素,应该使用ArrayList。
  • 对于“单线程环境” 或者 “多线程环境,但List仅仅只会被单个线程操作”,此时应该使用非同步的类(如ArrayList)。
  • 对于“多线程环境,且List可能同时被多个线程操作”,此时,应该使用同步的类(如Vector)。

LinkedList和ArrayList性能差异分析

问题一:为什么LinkedList中随机访问很慢,而ArrayList中随机访问很快

LinkedList找元素的过程:双向链表查找index位置的节点时,有一个加速动作:若index < 双向链表长度的1/2,则从前向后查找; 否则,从后向前查找。

ArrayList找元素的过程:直接返回数组中index位置的元素,而不需要像LinkedList一样进行查找。

问题二:为什么LinkedList中插入元素很快,而ArrayList中插入元素很慢

LinkedList插入过程

  • 不需要扩容,LinkedList的容量随着插入而增加
  • 根据index,找到对应元素,查找过程如上面
  • 在index位置插入元素,并且修改元素前后的指针就好,不需要移动元素

ArrayList插入过程

  • 确认ArrayList的容量,若容量不够,则增加容量。
  • 根据index找到元素,这个比较快
  • 插入元素后,会移动index之后所有元素,这就意味着,ArrayList的add(int index, E element)函数,会引起index之后所有元素的改变!
  • 注意:如果插入的是List的尾部,还是挺快的

Vector和ArrayList比较

相同之处

  1. 它们都是List,都继承于AbstractList

  2. 它们都实现了RandomAccess和Cloneable接口

  •   实现RandomAccess接口,意味着它们都支持快速随机访问;
  •   实现Cloneable接口,意味着它们能克隆自己。

  3. 它们都是通过数组实现的,本质上都是动态数组

  4. 它们的默认数组容量是10

  5. 它们都支持Iterator和listIterator遍历

不同之处

  1. 线程安全性不一样

  •   ArrayList是非线程安全;
  •   Vector是线程安全的,它的函数都是synchronized的,即都是支持同步的。
  •   ArrayList适用于单线程,Vector适用于多线程。

  2. 对序列化支持不同

  ArrayList支持序列化,而Vector不支持;即ArrayList有实现java.io.Serializable接口,而Vector没有实现该接口。

  3. 构造函数个数不同

  ArrayList有3个构造函数,而Vector有4个构造函数。Vector除了包括和ArrayList类似的3个构造函数之外,另外的一个构造函数可以指定容量增加系数。

  ArrayList的构造函数如下:

// 默认构造函数
ArrayList()

// capacity是ArrayList的默认容量大小。当由于增加数据导致容量不足时,容量会添加上一次容量大小的一半。
ArrayList(int capacity)

// 创建一个包含collection的ArrayList
ArrayList(Collection<? extends E> collection)

  Vector的构造函数如下:

// 默认构造函数
Vector()

// capacity是Vector的默认容量大小。当由于增加数据导致容量增加时,每次容量会增加一倍。
Vector(int capacity)

// 创建一个包含collection的Vector
Vector(Collection<? extends E> collection)

// capacity是Vector的默认容量大小,capacityIncrement是每次Vector容量增加时的增量值。
Vector(int capacity, int capacityIncrement)

  4. 扩容方式不同

  • ArrayList容量不足时,“新的容量”=“(原始容量x3)/2 + 1”。
  • Vector的容量增长与“增长系数有关”,若指定了“增长系数”,且“增长系数有效(即,大于0)”;那么,每次容量不足时,“新的容量”=“原始容量+增长系数”。若增长系数无效(即,小于/等于0),则“新的容量”=“原始容量 x 2”。

  5. 对Enumeration的支持不同。Vector支持通过Enumeration去遍历,而List不支持

猜你喜欢

转载自youyu4.iteye.com/blog/2388281