您的位置:首页 > 编程语言 > Java开发

Java基础之List实现篇

2016-03-26 22:42 726 查看

容器之List实现篇

[参考原文]/article/4709033.html

ArrayList

ArrayList简介

ArrayList 是一个 动态数组。与Java中的数组相比,它的容量能动态增长。它继承于AbstractList,实现了List, RandomAccess, Cloneable, java.io.Serializable这些接口。

ArrayList 继承了AbstractList,实现了List。它是一个数组队列,提供了相关的添加、删除、修改、遍历等功能。

ArrayList 实现了RandmoAccess接口,即提供了随机访问功能。RandmoAccess是java中用来被List实现,为List提供快速访问功能的。在ArrayList中,我们即可以通过元素的序号快速获取元素对象;这就是快速随机访问。稍后,我们会比较List的“快速随机访问”和“通过Iterator迭代器访问”的效率。

ArrayList 实现了Cloneable接口,即覆盖了函数clone(),能被克隆。

ArrayList 实现java.io.Serializable接口,这意味着ArrayList支持序列化,能通过序列化去传输。

和Vector不同,ArrayList中的操作不是线程安全的!所以,建议在单线程中才使用ArrayList,而在多线程中可以选择Vector或者CopyOnWriteArrayList。

ArrayList数据结构

java.lang.Object
↳     java.util.AbstractCollection<E>
↳     java.util.AbstractList<E>
↳     java.util.ArrayList<E>

public class ArrayList<E> extends AbstractList<E>
implements List<E>, RandomAccess, Cloneable, java.io.Serializable {}


ArrayList与Collection关系如下图:



ArrayList包含了两个重要的对象:elementData 和 size。

elementData 是”Object[]类型的数组”,它保存了添加到ArrayList中的元素。实际上,elementData是个动态数组,我们能通过构造函数 ArrayList(int initialCapacity)来执行它的初始容量为initialCapacity;如果通过不含参数的构造函数ArrayList()来创建ArrayList,则elementData的容量默认是10。elementData数组的大小会根据ArrayList容量的增长而动态的增长,具体的增长方式,请参考源码分析中的ensureCapacity()函数。

size 则是动态数组的实际大小。

ArrayList构造函数

// 默认构造函数
ArrayList()

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

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


ArrayList的API

// Collection中定义的API
boolean             add(E object)
boolean             addAll(Collection<? extends E> collection)
void                clear()
boolean             contains(Object object)
boolean             containsAll(Collection<?> collection)
boolean             equals(Object object)
int                 hashCode()
boolean             isEmpty()
Iterator<E>         iterator()
boolean             remove(Object object)
boolean             removeAll(Collection<?> collection)
boolean             retainAll(Collection<?> collection)
int                 size()
<T> T[]             toArray(T[] array)
Object[]            toArray()
// AbstractCollection中定义的API
void                add(int location, E object)
boolean             addAll(int location, Collection<? extends E> collection)
E                   get(int location)
int                 indexOf(Object object)
int                 lastIndexOf(Object object)
ListIterator<E>     listIterator(int location)
ListIterator<E>     listIterator()
E                   remove(int location)
E                   set(int location, E object)
List<E>             subList(int start, int end)
// ArrayList新增的API
Object               clone()
void                 ensureCapacity(int minimumCapacity)
void                 trimToSize()
void                 removeRange(int fromIndex, int toIndex)


源码分析

package java.util;

public class ArrayList<E> extends AbstractList<E>
implements List<E>, RandomAccess, Cloneable, java.io.Serializable
{
// 序列版本号
private static final long serialVersionUID = 8683452581122892189L;

// 保存ArrayList中数据的数组
private transient Object[] elementData;

// ArrayList中实际数据的数量
private int size;

// ArrayList带容量大小的构造函数。
public ArrayList(int initialCapacity) {
super();
if (initialCapacity < 0)
throw new IllegalArgumentException("Illegal Capacity: "+
initialCapacity);
// 新建一个数组
this.elementData = new Object[initialCapacity];
}

// ArrayList构造函数。默认容量是10。
public ArrayList() {
this(10);
}

// 创建一个包含collection的ArrayList
public ArrayList(Collection<? extends E> c) {
elementData = c.toArray();
size = elementData.length;
// c.toArray might (incorrectly) not return Object[] (see 6260652)
if (elementData.getClass() != Object[].class)
elementData = Arrays.copyOf(elementData, size, Object[].class);
}

// 将当前容量值设为 =实际元素个数
public void trimToSize() {
modCount++;
int oldCapacity = elementData.length;
if (size < oldCapacity) {
elementData = Arrays.copyOf(elementData, size);
}
}

// 确定ArrarList的容量。
// 若ArrayList的容量不足以容纳当前的全部元素,设置 新的容量=“(原始容量x3)/2 + 1”
public void ensureCapacity(int minCapacity) {
// 将“修改统计数”+1
modCount++;
int oldCapacity = elementData.length;
// 若当前容量不足以容纳当前的元素个数,设置 新的容量=“(原始容量x3)/2 + 1”
if (minCapacity > oldCapacity) {
Object oldData[] = elementData;
int newCapacity = (oldCapacity * 3)/2 + 1;
if (newCapacity < minCapacity)
newCapacity = minCapacity;
elementData = Arrays.copyOf(elementData, newCapacity);
}
}

// 添加元素e
public boolean add(E e) {
// 确定ArrayList的容量大小
ensureCapacity(size + 1);  // Increments modCount!!
// 添加e到ArrayList中
elementData[size++] = e;
return true;
}

// 返回ArrayList的实际大小
public int size() {
return size;
}

// 返回ArrayList是否包含Object(o)
public boolean contains(Object o) {
return indexOf(o) >= 0;
}

// 返回ArrayList是否为空
public boolean isEmpty() {
return size == 0;
}

// 正向查找,返回元素的索引值
public int indexOf(Object o) {
if (o == null) {
for (int i = 0; i < size; i++)
if (elementData[i]==null)
return i;
} else {
for (int i = 0; i < size; i++)
if (o.equals(elementData[i]))
return i;
}
return -1;
}

// 反向查找,返回元素的索引值
public int lastIndexOf(Object o) {
if (o == null) {
for (int i = size-1; i >= 0; i--)
if (elementData[i]==null)
return i;
} else {
for (int i = size-1; i >= 0; i--)
if (o.equals(elementData[i]))
return i;
}
return -1;
}

// 反向查找(从数组末尾向开始查找),返回元素(o)的索引值
public int lastIndexOf(Object o) {
if (o == null) {
for (int i = size-1; i >= 0; i--)
if (elementData[i]==null)
return i;
} else {
for (int i = size-1; i >= 0; i--)
if (o.equals(elementData[i]))
return i;
}
return -1;
}

// 返回ArrayList的Object数组
public Object[] toArray() {
return Arrays.copyOf(elementData, size);
}

// 返回ArrayList的模板数组。所谓模板数组,即可以将T设为任意的数据类型
public <T> T[] toArray(T[] a) {
// 若数组a的大小 < ArrayList的元素个数;
// 则新建一个T[]数组,数组大小是“ArrayList的元素个数”,并将“ArrayList”全部拷贝到新数组中
if (a.length < size)
return (T[]) Arrays.copyOf(elementData, size, a.getClass());

// 若数组a的大小 >= ArrayList的元素个数;
// 则将ArrayList的全部元素都拷贝到数组a中。
System.arraycopy(elementData, 0, a, 0, size);
if (a.length > size)
a[size] = null;
return a;
}

// 获取index位置的元素值
public E get(int index) {
RangeCheck(index);

return (E) elementData[index];
}

// 设置index位置的值为element
public E set(int index, E element) {
RangeCheck(index);

E oldValue = (E) elementData[index];
elementData[index] = element;
return oldValue;
}

// 将e添加到ArrayList中
public boolean add(E e) {
ensureCapacity(size + 1);  // Increments modCount!!
elementData[size++] = e;
return true;
}

// 将e添加到ArrayList的指定位置
public void add(int index, E element) {
if (index > size || index < 0)
throw new IndexOutOfBoundsException(
"Index: "+index+", Size: "+size);

ensureCapacity(size+1);  // Increments modCount!!
System.arraycopy(elementData, index, elementData, index + 1,
size - index);
elementData[index] = element;
size++;
}

// 删除ArrayList指定位置的元素
public E remove(int index) {
RangeCheck(index);

modCount++;
E oldValue = (E) elementData[index];

int numMoved = size - index - 1;
if (numMoved > 0)
System.arraycopy(elementData, index+1, elementData, index,
numMoved);
elementData[--size] = null; // Let gc do its work

return oldValue;
}

// 删除ArrayList的指定元素
public boolean remove(Object o) {
if (o == null) {
for (int index = 0; index < size; index++)
if (elementData[index] == null) {
fastRemove(index);
return true;
}
} else {
for (int index = 0; index < size; index++)
if (o.equals(elementData[index])) {
fastRemove(index);
return true;
}
}
return false;
}

// 快速删除第index个元素
private void fastRemove(int index) {
modCount++;
int numMoved = size - index - 1;
// 从"index+1"开始,用后面的元素替换前面的元素。
if (numMoved > 0)
System.arraycopy(elementData, index+1, elementData, index,
numMoved);
// 将最后一个元素设为null
elementData[--size] = null; // Let gc do its work
}

// 删除元素
public boolean remove(Object o) {
if (o == null) {
for (int index = 0; index < size; index++)
if (elementData[index] == null) {
fastRemove(index);
return true;
}
} else {
// 便利ArrayList,找到“元素o”,则删除,并返回true。
for (int index = 0; index < size; index++)
if (o.equals(elementData[index])) {
fastRemove(index);
return true;
}
}
return false;
}

// 清空ArrayList,将全部的元素设为null
public void clear() {
modCount++;

for (int i = 0; i < size; i++)
elementData[i] = null;

size = 0;
}

// 将集合c追加到ArrayList中
public boolean addAll(Collection<? extends E> c) {
Object[] a = c.toArray();
int numNew = a.length;
ensureCapacity(size + numNew);  // Increments modCount
System.arraycopy(a, 0, elementData, size, numNew);
size += numNew;
return numNew != 0;
}

// 从index位置开始,将集合c添加到ArrayList
public boolean addAll(int index, Collection<? extends E> c) {
if (index > size || index < 0)
throw new IndexOutOfBoundsException(
"Index: " + index + ", Size: " + size);

Object[] a = c.toArray();
int numNew = a.length;
ensureCapacity(size + numNew);  // Increments modCount

int numMoved = size - index;
if (numMoved > 0)
System.arraycopy(elementData, index, elementData, index + numNew,
numMoved);

System.arraycopy(a, 0, elementData, index, numNew);
size += numNew;
return numNew != 0;
}

// 删除fromIndex到toIndex之间的全部元素。
protected void removeRange(int fromIndex, int toIndex) {
modCount++;
int numMoved = size - toIndex;
System.arraycopy(elementData, toIndex, elementData, fromIndex,
numMoved);

// Let gc do its work
int newSize = size - (toIndex-fromIndex);
while (size != newSize)
elementData[--size] = null;
}

private void RangeCheck(int index) {
if (index >= size)
throw new IndexOutOfBoundsException(
"Index: "+index+", Size: "+size);
}

// 克隆函数
public Object clone() {
try {
ArrayList<E> v = (ArrayList<E>) super.clone();
// 将当前ArrayList的全部元素拷贝到v中
v.elementData = Arrays.copyOf(elementData, size);
v.modCount = 0;
return v;
} catch (CloneNotSupportedException e) {
// this shouldn't happen, since we are Cloneable
throw new InternalError();
}
}

// java.io.Serializable的写入函数
// 将ArrayList的“容量,所有的元素值”都写入到输出流中
private void writeObject(java.io.ObjectOutputStream s)
throws java.io.IOException{
// Write out element count, and any hidden stuff
int expectedModCount = modCount;
s.defaultWriteObject();

// 写入“数组的容量”
s.writeInt(elementData.length);

// 写入“数组的每一个元素”
for (int i=0; i<size; i++)
s.writeObject(elementData[i]);

if (modCount != expectedModCount) {
throw new ConcurrentModificationException();
}

}

// java.io.Serializable的读取函数:根据写入方式读出
// 先将ArrayList的“容量”读出,然后将“所有的元素值”读出
private void readObject(java.io.ObjectInputStream s)
throws java.io.IOException, ClassNotFoundException {
// Read in size, and any hidden stuff
s.defaultReadObject();

// 从输入流中读取ArrayList的“容量”
int arrayLength = s.readInt();
Object[] a = elementData = new Object[arrayLength];

// 从输入流中将“所有的元素值”读出
for (int i=0; i<size; i++)
a[i] = s.readObject();
}
}


ArrayList 实际上是通过一个数组去保存数据的。当我们构造ArrayList时;若使用默认构造函数,则ArrayList的默认容量大小是10。

当ArrayList容量不足以容纳全部元素时,ArrayList会重新设置容量:新的容量=“(原始容量x3)/2 + 1”。

ArrayList的克隆函数,即是将全部元素克隆到一个数组中。

ArrayList实现java.io.Serializable的方式。当写入到输出流时,先写入“容量”,再依次写入“每一个元素”;当读出输入流时,先读取“容量”,再依次读取“每一个元素”。

ArrayList遍历方式

1. 第一种,通过迭代器遍历。即通过Iterator去遍历。

Integer value = null;
Iterator iter = list.iterator();
while (iter.hasNext()) {
value = (Integer)iter.next();
}  //通过迭代器访问速率最慢


2. 第二种,随机访问,通过索引值去遍历。

由于ArrayList实现了RandomAccess接口,它支持通过索引值去随机访问元素。

Integer value = null;
int size = list.size();
for (int i=0; i<size; i++) {
value = (Integer)list.get(i);
}//这种随机访问方式速度最快


3. 第三种,for循环遍历。如下:

Integer value = null;
for (Integer integ:list) {
value = integ;
}   //速度次之


遍历ArrayList时,使用随机访问(即,通过索引序号访问)效率最高,而使用迭代器的效率最低!

toArray()异常

当我们调用ArrayList中的 toArray(),可能遇到过抛出“java.lang.ClassCastException”异常的情况。下面我们说说这是怎么回事。

ArrayList提供了2个toArray()函数:

Object[] toArray()

< T > T[] toArray(T[] contents)

调用 toArray() 函数会抛出“java.lang.ClassCastException”异常,但是调用 toArray(T[] contents) 能正常返回 T[]。

toArray() 会抛出异常是因为 toArray() 返回的是 Object[] 数组,将 Object[] 转换为其它类型(如如,将Object[]转换为的Integer[])则会抛出“java.lang.ClassCastException”异常,因为Java不支持向下转型。具体的可以参考前面ArrayList.java的源码介绍部分的toArray()。

解决该问题的办法是调用 T[] toArray(T[] contents) , 而不是 Object[] toArray()。

调用 toArray(T[] contents) 返回T[]的可以通过以下几种方式实现。

// toArray(T[] contents)调用方式一
public static Integer[] vectorToArray1(ArrayList<Integer> v) {
Integer[] newText = new Integer[v.size()];
v.toArray(newText);
return newText;
}

// toArray(T[] contents)调用方式二。最常用!
public static Integer[] vectorToArray2(ArrayList<Integer> v) {
Integer[] newText = (Integer[])v.toArray(new Integer[0]);
return newText;
}

// toArray(T[] contents)调用方式三
public static Integer[] vectorToArray3(ArrayList<Integer> v) {
Integer[] newText = new Integer[v.size()];
Integer[] newStrings = (Integer[])v.toArray(newText);
return newStrings;
}


ArrayList实例

ppublic class Test {
public static void main(String[] args) {

// 创建ArrayList
ArrayList<Integer> list = new ArrayList<Integer>();

for(int i=0;i<5;i++){
list.add(i);//添加元素
}
System.out.println(list.toString());

//在2的位置插入3,原来位置的元素向后移
list.add(2, 3);

//将下标为1上的元素设为10;
list.set(1,10);

//遍历ArrayList,获取list.size(),获取其中元素
for(int i=0;i<list.size();i++){
System.out.print(list.get(i)+" ");
}
System.out.println();

//删除元素,一次只能删除一个,注意new Integer(3)按元素删除
list.remove(new Integer(3));
System.out.println(list.toString());

//按下标删除
list.remove(0);
System.out.println(list.toString());

// 判断list中是否包含"3"
System.out.println("ArrayList contains 3 is: "+ list.contains(3));

// 通过Iterator遍历ArrayList
for(Iterator iter = list.iterator(); iter.hasNext(); ) {
System.out.print(iter.next()+" ");
}
System.out.println();

// 将ArrayList转换为数组
Integer[] arr=new Integer[list.size()];
list.toArray(arr);

//数组arr
for (Integer str:arr)
System.out.print(str+" ");
System.out.println();
// 清空ArrayList
list.clear();

// 判断ArrayList是否为空
System.out.println("ArrayList is empty: "+ list.isEmpty());
}

}


输出:

[0, 1, 2, 3, 4]

0 10 3 2 3 4

[0, 10, 2, 3, 4]

[10, 2, 3, 4]

ArrayList contains 3 is: true

10 2 3 4

10 2 3 4

ArrayList is empty: true

LinkedList

概述

LinkedList 是一个继承于AbstractSequentialList的双向链表。它也可以被当作堆栈、队列或双端队列进行操作。

LinkedList 实现 List 接口,能对它进行队列操作。

LinkedList 实现 Deque 接口,即能将LinkedList当作双端队列使用。

LinkedList 实现了Cloneable接口,即覆盖了函数clone(),能克隆。

LinkedList 实现java.io.Serializable接口,这意味着LinkedList支持序列化,能通过序列化去传输。

LinkedList 是非同步的,即非线程安全

数据结构

java.lang.Object
↳     java.util.AbstractCollection<E>
↳     java.util.AbstractList<E>
↳     java.util.AbstractSequentialList<E>
↳     java.util.LinkedList<E>

public class LinkedList<E>
extends AbstractSequentialList<E>
implements List<E>, Deque<E>, Cloneable, java.io.Serializable {}




LinkedList的本质是双向链表。

LinkedList继承于AbstractSequentialList,并且实现了Dequeue接口。

LinkedList包含两个重要的成员:header 和 size。

header是双向链表的表头,它是双向链表节点所对应的类Entry的实例。Entry中包含成员变量: previous, next, element。其中,previous是该节点的上一个节点,next是该节点的下一个节点,element是该节点所包含的值。

 size是双向链表中节点的个数。

构造函数

// 默认构造函数
LinkedList()

// 创建一个LinkedList,保护Collection中的全部元素。
LinkedList(Collection<? extends E> collection)


API

LinkedList的API
boolean       add(E object)
void          add(int location, E object)
boolean       addAll(Collection<? extends E> collection)
boolean       addAll(int location, Collection<? extends E> collection)
void          addFirst(E object)
void          addLast(E object)
void          clear()
Object        clone()
boolean       contains(Object object)
Iterator<E>   descendingIterator()
E             element()
E             get(int location)
E             getFirst()
E             getLast()
int           indexOf(Object object)
int           lastIndexOf(Object object)
ListIterator<E>     listIterator(int location)
boolean       offer(E o)
boolean       offerFirst(E e)
boolean       offerLast(E e)
E             peek()
E             peekFirst()
E             peekLast()
E             poll()
E             pollFirst()
E             pollLast()
E             pop()
void          push(E e)
E             remove()
E             remove(int location)
boolean       remove(Object object)
E             removeFirst()
boolean       removeFirstOccurrence(Object o)
E             removeLast()
boolean       removeLastOccurrence(Object o)
E             set(int location, E object)
int           size()
<T> T[]       toArray(T[] contents)
Object[]     toArray()


AbstractSequentialList简介

在介绍LinkedList的源码之前,先介绍一下AbstractSequentialList。毕竟,LinkedList是AbstractSequentialList的子类。

AbstractSequentialList 实现了get(int index)、set(int index, E element)、add(int index, E element) 和 remove(int index)这些函数。这些接口都是随机访问List的,LinkedList是双向链表;既然它继承于AbstractSequentialList,就相当于已经实现了“get(int index)这些接口”。

此外,我们若需要通过AbstractSequentialList自己实现一个列表,只需要扩展此类,并提供 listIterator() 和 size() 方法的实现即可。若要实现不可修改的列表,则需要实现列表迭代器的 hasNext、next、hasPrevious、previous 和 index 方法即可。

LinkedList源码解析

为了更了解LinkedList的原理,下面对LinkedList源码代码作出分析。

在阅读源码之前,我们先对LinkedList的整体实现进行大致说明:

LinkedList实际上是通过双向链表去实现的。既然是双向链表,那么它的顺序访问会非常高效,而随机访问效率比较低。

既然LinkedList是通过双向链表的,但是它也实现了List接口{也就是说,它实现了get(int location)、remove(int location)等“根据索引值来获取、删除节点的函数”}。LinkedList是如何实现List的这些接口的,如何将“双向链表和索引值联系起来的”?

实际原理非常简单,它就是通过一个计数索引值来实现的。例如,当我们调用get(int location)时,首先会比较“location”和“双向链表长度的1/2”;若前者大,则从链表头开始往后查找,直到location位置;否则,从链表末尾开始先前查找,直到location位置。


这就是“双线链表和索引值联系起来”的方法。

package java.util;

public class LinkedList<E>
extends AbstractSequentialList<E>
implements List<E>, Deque<E>, Cloneable, java.io.Serializable
{
// 链表的表头,表头不包含任何数据。Entry是个链表类数据结构。
private transient Entry<E> header = new Entry<E>(null, null, null);

// LinkedList中元素个数
private transient int size = 0;

// 默认构造函数:创建一个空的链表
public LinkedList() {
header.next = header.previous = header;
}

// 包含“集合”的构造函数:创建一个包含“集合”的LinkedList
public LinkedList(Collection<? extends E> c) {
this();
addAll(c);
}

// 获取LinkedList的第一个元素
public E getFirst() {
if (size==0)
throw new NoSuchElementException();

// 链表的表头header中不包含数据。
// 这里返回header所指下一个节点所包含的数据。
return header.next.element;
}

// 获取LinkedList的最后一个元素
public E getLast()  {
if (size==0)
throw new NoSuchElementException();

// 由于LinkedList是双向链表;而表头header不包含数据。
// 因而,这里返回表头header的前一个节点所包含的数据。
return header.previous.element;
}

// 删除LinkedList的第一个元素
public E removeFirst() {
return remove(header.next);
}

// 删除LinkedList的最后一个元素
public E removeLast() {
return remove(header.previous);
}

// 将元素添加到LinkedList的起始位置
public void addFirst(E e) {
addBefore(e, header.next);
}

// 将元素添加到LinkedList的结束位置
public void addLast(E e) {
addBefore(e, header);
}

// 判断LinkedList是否包含元素(o)
public boolean contains(Object o) {
return indexOf(o) != -1;
}

// 返回LinkedList的大小
public int size() {
return size;
}

// 将元素(E)添加到LinkedList中
public boolean add(E e) {
// 将节点(节点数据是e)添加到表头(header)之前。
// 即,将节点添加到双向链表的末端。
addBefore(e, header);
return true;
}

// 从LinkedList中删除元素(o)
// 从链表开始查找,如存在元素(o)则删除该元素并返回true;
// 否则,返回false。
public boolean remove(Object o) {
if (o==null) {
// 若o为null的删除情况
for (Entry<E> e = header.next; e != header; e = e.next) {
if (e.element==null) {
remove(e);
return true;
}
}
} else {
// 若o不为null的删除情况
for (Entry<E> e = header.next; e != header; e = e.next) {
if (o.equals(e.element)) {
remove(e);
return true;
}
}
}
return false;
}

// 将“集合(c)”添加到LinkedList中。
// 实际上,是从双向链表的末尾开始,将“集合(c)”添加到双向链表中。
public boolean addAll(Collection<? extends E> c) {
return addAll(size, c);
}

// 从双向链表的index开始,将“集合(c)”添加到双向链表中。
public boolean addAll(int index, Collection<? extends E> c) {
if (index < 0 || index > size)
throw new IndexOutOfBoundsException("Index: "+index+
", Size: "+size);
Object[] a = c.toArray();
// 获取集合的长度
int numNew = a.length;
if (numNew==0)
return false;
modCount++;

// 设置“当前要插入节点的后一个节点”
Entry<E> successor = (index==size ? header : entry(index));
// 设置“当前要插入节点的前一个节点”
Entry<E> predecessor = successor.previous;
// 将集合(c)全部插入双向链表中
for (int i=0; i<numNew; i++) {
Entry<E> e = new Entry<E>((E)a[i], successor, predecessor);
predecessor.next = e;
predecessor = e;
}
successor.previous = predecessor;

// 调整LinkedList的实际大小
size += numNew;
return true;
}

// 清空双向链表
public void clear() {
Entry<E> e = header.next;
// 从表头开始,逐个向后遍历;对遍历到的节点执行一下操作:
// (01) 设置前一个节点为null
// (02) 设置当前节点的内容为null
// (03) 设置后一个节点为“新的当前节点”
while (e != header) {
Entry<E> next = e.next;
e.next = e.previous = null;
e.element = null;
e = next;
}
header.next = header.previous = header;
// 设置大小为0
size = 0;
modCount++;
}

// 返回LinkedList指定位置的元素
public E get(int index) {
return entry(index).element;
}

// 设置index位置对应的节点的值为element
public E set(int index, E element) {
Entry<E> e = entry(index);
E oldVal = e.element;
e.element = element;
return oldVal;
}

// 在index前添加节点,且节点的值为element
public void add(int index, E element) {
addBefore(element, (index==size ? header : entry(index)));
}

// 删除index位置的节点
public E remove(int index) {
return remove(entry(index));
}

// 获取双向链表中指定位置的节点
private Entry<E> entry(int index) {
if (index < 0 || index >= size)
throw new IndexOutOfBoundsException("Index: "+index+
", Size: "+size);
Entry<E> e = header;
// 获取index处的节点。
// 若index < 双向链表长度的1/2,则从前先后查找;
// 否则,从后向前查找。
if (index < (size >> 1)) {
for (int i = 0; i <= index; i++)
e = e.next;
} else {
for (int i = size; i > index; i--)
e = e.previous;
}
return e;
}

// 从前向后查找,返回“值为对象(o)的节点对应的索引”
// 不存在就返回-1
public int indexOf(Object o) {
int index = 0;
if (o==null) {
for (Entry e = header.next; e != header; e = e.next) {
if (e.element==null)
return index;
index++;
}
} else {
for (Entry e = header.next; e != header; e = e.next) {
if (o.equals(e.element))
return index;
index++;
}
}
return -1;
}

// 从后向前查找,返回“值为对象(o)的节点对应的索引”
// 不存在就返回-1
public int lastIndexOf(Object o) {
int index = size;
if (o==null) {
for (Entry e = header.previous; e != header; e = e.previous) {
index--;
if (e.element==null)
return index;
}
} else {
for (Entry e = header.previous; e != header; e = e.previous) {
index--;
if (o.equals(e.element))
return index;
}
}
return -1;
}

// 返回第一个节点
// 若LinkedList的大小为0,则返回null
public E peek() {
if (size==0)
return null;
return getFirst();
}

// 返回第一个节点
// 若LinkedList的大小为0,则抛出异常
public E element() {
return getFirst();
}

// 删除并返回第一个节点
// 若LinkedList的大小为0,则返回null
public E poll() {
if (size==0)
return null;
return removeFirst();
}

// 将e添加双向链表末尾
public boolean offer(E e) {
return add(e);
}

// 将e添加双向链表开头
public boolean offerFirst(E e) {
addFirst(e);
return true;
}

// 将e添加双向链表末尾
public boolean offerLast(E e) {
addLast(e);
return true;
}

// 返回第一个节点
// 若LinkedList的大小为0,则返回null
public E peekFirst() {
if (size==0)
return null;
return getFirst();
}

// 返回最后一个节点
// 若LinkedList的大小为0,则返回null
public E peekLast() {
if (size==0)
return null;
return getLast();
}

// 删除并返回第一个节点
// 若LinkedList的大小为0,则返回null
public E pollFirst() {
if (size==0)
return null;
return removeFirst();
}

// 删除并返回最后一个节点
// 若LinkedList的大小为0,则返回null
public E pollLast() {
if (size==0)
return null;
return removeLast();
}

// 将e插入到双向链表开头
public void push(E e) {
addFirst(e);
}

// 删除并返回第一个节点
public E pop() {
return removeFirst();
}

// 从LinkedList开始向后查找,删除第一个值为元素(o)的节点
// 从链表开始查找,如存在节点的值为元素(o)的节点,则删除该节点
public boolean removeFirstOccurrence(Object o) {
return remove(o);
}

// 从LinkedList末尾向前查找,删除第一个值为元素(o)的节点
// 从链表开始查找,如存在节点的值为元素(o)的节点,则删除该节点
public boolean removeLastOccurrence(Object o) {
if (o==null) {
for (Entry<E> e = header.previous; e != header; e = e.previous) {
if (e.element==null) {
remove(e);
return true;
}
}
} else {
for (Entry<E> e = header.previous; e != header; e = e.previous) {
if (o.equals(e.element)) {
remove(e);
return true;
}
}
}
return false;
}

// 返回“index到末尾的全部节点”对应的ListIterator对象(List迭代器)
public ListIterator<E> listIterator(int index) {
return new ListItr(index);
}

// List迭代器
private class ListItr implements ListIterator<E> {
// 上一次返回的节点
private Entry<E> lastReturned = header;
// 下一个节点
private Entry<E> next;
// 下一个节点对应的索引值
private int nextIndex;
// 期望的改变计数。用来实现fail-fast机制。
private int expectedModCount = modCount;

// 构造函数。
// 从index位置开始进行迭代
ListItr(int index) {
// index的有效性处理
if (index < 0 || index > size)
throw new IndexOutOfBoundsException("Index: "+index+ ", Size: "+size);
// 若 “index 小于 ‘双向链表长度的一半’”,则从第一个元素开始往后查找;
// 否则,从最后一个元素往前查找。
if (index < (size >> 1)) {
next = header.next;
for (nextIndex=0; nextIndex<index; nextIndex++)
next = next.next;
} else {
next = header;
for (nextIndex=size; nextIndex>index; nextIndex--)
next = next.previous;
}
}

// 是否存在下一个元素
public boolean hasNext() {
// 通过元素索引是否等于“双向链表大小”来判断是否达到最后。
return nextIndex != size;
}

// 获取下一个元素
public E next() {
checkForComodification();
if (nextIndex == size)
throw new NoSuchElementException();

lastReturned = next;
// next指向链表的下一个元素
next = next.next;
nextIndex++;
return lastReturned.element;
}

// 是否存在上一个元素
public boolean hasPrevious() {
// 通过元素索引是否等于0,来判断是否达到开头。
return nextIndex != 0;
}

// 获取上一个元素
public E previous() {
if (nextIndex == 0)
throw new NoSuchElementException();

// next指向链表的上一个元素
lastReturned = next = next.previous;
nextIndex--;
checkForComodification();
return lastReturned.element;
}

// 获取下一个元素的索引
public int nextIndex() {
return nextIndex;
}

// 获取上一个元素的索引
public int previousIndex() {
return nextIndex-1;
}

// 删除当前元素。
// 删除双向链表中的当前节点
public void remove() {
checkForComodification();
Entry<E> lastNext = lastReturned.next;
try {
LinkedList.this.remove(lastReturned);
} catch (NoSuchElementException e) {
throw new IllegalStateException();
}
if (next==lastReturned)
next = lastNext;
else
nextIndex--;
lastReturned = header;
expectedModCount++;
}

// 设置当前节点为e
public void set(E e) {
if (lastReturned == header)
throw new IllegalStateException();
checkForComodification();
lastReturned.element = e;
}

// 将e添加到当前节点的前面
public void add(E e) {
checkForComodification();
lastReturned = header;
addBefore(e, next);
nextIndex++;
expectedModCount++;
}

// 判断 “modCount和expectedModCount是否相等”,依次来实现fail-fast机制。
final void checkForComodification() {
if (modCount != expectedModCount)
throw new ConcurrentModificationException();
}
}

// 双向链表的节点所对应的数据结构。
// 包含3部分:上一节点,下一节点,当前节点值。
private static class Entry<E> {
// 当前节点所包含的值
E element;
// 下一个节点
Entry<E> next;
// 上一个节点
Entry<E> previous;

/**
* 链表节点的构造函数。
* 参数说明:
*   element  —— 节点所包含的数据
*   next      —— 下一个节点
*   previous —— 上一个节点
*/
Entry(E element, Entry<E> next, Entry<E> previous) {
this.element = element;
this.next = next;
this.previous = previous;
}
}

// 将节点(节点数据是e)添加到entry节点之前。
private Entry<E> addBefore(E e, Entry<E> entry) {
// 新建节点newEntry,将newEntry插入到节点e之前;并且设置newEntry的数据是e
Entry<E> newEntry = new Entry<E>(e, entry, entry.previous);
newEntry.previous.next = newEntry;
newEntry.next.previous = newEntry;
// 修改LinkedList大小
size++;
// 修改LinkedList的修改统计数:用来实现fail-fast机制。
modCount++;
return newEntry;
}

// 将节点从链表中删除
private E remove(Entry<E> e) {
if (e == header)
throw new NoSuchElementException();

E result = e.element;
e.previous.next = e.next;
e.next.previous = e.previous;
e.next = e.previous = null;
e.element = null;
size--;
modCount++;
return result;
}

// 反向迭代器
public Iterator<E> descendingIterator() {
return new DescendingIterator();
}

// 反向迭代器实现类。
private class DescendingIterator implements Iterator {
final ListItr itr = new ListItr(size());
// 反向迭代器是否下一个元素。
// 实际上是判断双向链表的当前节点是否达到开头
public boolean hasNext() {
return itr.hasPrevious();
}
// 反向迭代器获取下一个元素。
// 实际上是获取双向链表的前一个节点
public E next() {
return itr.previous();
}
// 删除当前节点
public void remove() {
itr.remove();
}
}

// 返回LinkedList的Object[]数组
public Object[] toArray() {
// 新建Object[]数组
Object[] result = new Object[size];
int i = 0;
// 将链表中所有节点的数据都添加到Object[]数组中
for (Entry<E> e = header.next; e != header; e = e.next)
result[i++] = e.element;
return result;
}

// 返回LinkedList的模板数组。所谓模板数组,即可以将T设为任意的数据类型
public <T> T[] toArray(T[] a) {
// 若数组a的大小 < LinkedList的元素个数(意味着数组a不能容纳LinkedList中全部元素)
// 则新建一个T[]数组,T[]的大小为LinkedList大小,并将该T[]赋值给a。
if (a.length < size)
a = (T[])java.lang.reflect.Array.newInstance(
a.getClass().getComponentType(), size);
// 将链表中所有节点的数据都添加到数组a中
int i = 0;
Object[] result = a;
for (Entry<E> e = header.next; e != header; e = e.next)
result[i++] = e.element;

if (a.length > size)
a[size] = null;

return a;
}

// 克隆函数。返回LinkedList的克隆对象。
public Object clone() {
LinkedList<E> clone = null;
// 克隆一个LinkedList克隆对象
try {
clone = (LinkedList<E>) super.clone();
} catch (CloneNotSupportedException e) {
throw new InternalError();
}

// 新建LinkedList表头节点
clone.header = new Entry<E>(null, null, null);
clone.header.next = clone.header.previous = clone.header;
clone.size = 0;
clone.modCount = 0;

// 将链表中所有节点的数据都添加到克隆对象中
for (Entry<E> e = header.next; e != header; e = e.next)
clone.add(e.element);

return clone;
}

// java.io.Serializable的写入函数
// 将LinkedList的“容量,所有的元素值”都写入到输出流中
private void writeObject(java.io.ObjectOutputStream s)
throws java.io.IOException {
// Write out any hidden serialization magic
s.defaultWriteObject();

// 写入“容量”
s.writeInt(size);

// 将链表中所有节点的数据都写入到输出流中
for (Entry e = header.next; e != header; e = e.next)
s.writeObject(e.element);
}

// java.io.Serializable的读取函数:根据写入方式反向读出
// 先将LinkedList的“容量”读出,然后将“所有的元素值”读出
private void readObject(java.io.ObjectInputStream s)
throws java.io.IOException, ClassNotFoundException {
// Read in any hidden serialization magic
s.defaultReadObject();

// 从输入流中读取“容量”
int size = s.readInt();

// 新建链表表头节点
header = new Entry<E>(null, null, null);
header.next = header.previous = header;

// 从输入流中将“所有的元素值”并逐个添加到链表中
for (int i=0; i<size; i++)
addBefore((E)s.readObject(), header);
}

}


LinkedList实际上是通过双向链表去实现的。既然是双向链表,那么它的顺序访问会非常高效,可以随机访问(通过下标访问)但是随机访问效率比较低.它包含一个非常重要的内部类:Entry。Entry是双向链表节点所对应的数据结构,它包括的属性有:当前节点所包含的值,上一个节点,下一个节点。

从LinkedList的实现方式中可以发现,它不存在LinkedList容量不足的问题。

LinkedList的克隆函数,即是将全部元素克隆到一个新的LinkedList对象中。

LinkedList实现java.io.Serializable。当写入到输出流时,先写入“容量”,再依次写入“每一个节点保护的值”;当读出输入流时,先读取“容量”,再依次读取“每一个元素”。

由于LinkedList实现了Deque,而Deque接口定义了在双端队列两端访问元素的方法。提供插入、移除和检查元素的方法。每种方法都存在两种形式:一种形式在操作失败时抛出异常,另一种形式返回一个特殊值(null 或 false,具体取决于操作)。



LinkedList遍历方式

方式一:推荐:最好

for (Integer integ:list)
;


方式二:注意try..catch异常

try {
while(list.removeFirst() != null)
;
} catch (NoSuchElementException e) {
}//removeFist()或removeLast()效率最高,但是会删除头或尾元素


方式三:

for(Iterator iter = list.iterator(); iter.hasNext();)
iter.next();


方式四:

int size = list.size();
for (int i=0; i<size; i++) {
list.get(i);
}//这种快速随机访问,效率最低


由此可见,遍历LinkedList时,使用removeFist()或removeLast()效率最高。但用它们遍历时,会删除原始数据;若单纯只读取,而不删除,应该使用第1种遍历方式。

无论如何,千万不要通过随机访问去遍历LinkedList!

实例

public class Test {
public static void main(String[] args) {
// 测试LinkedList的API
testLinkedListAPIs() ;

// 将LinkedList当作 LIFO(后进先出)的堆栈
useLinkedListAsLIFO();

// 将LinkedList当作 FIFO(先进先出)的队列
useLinkedListAsFIFO();
}

/*
* 测试LinkedList中部分API
*/
private static void testLinkedListAPIs() {

// 新建一个LinkedList
LinkedList<Integer> llist = new LinkedList<Integer>();

//---- 添加操作 ----
for(int i=0;i<5;i++)
llist.add(i);
System.out.println(llist.toString());

//在下标为2的位置添加5,原来位置上的元素向后移
llist.add(2, 5);
System.out.println("llist.add(2, 5):"+llist.toString());

System.out.println("\n链表头操作...");
// (01) 将6添加到第一个位置。  失败的话,抛出异常!
llist.addFirst(6);
System.out.println("addFirst(6):"+llist);

// (02) 删除并弹出第一个元素。        失败的话,抛出异常!
int firstword = llist.removeFirst();
System.out.println("llist.removeFirst()返回:"+firstword);
System.out.println("llist:"+llist);

// (03) 获取第一个元素。          失败的话,抛出异常!
System.out.println("llist.getFirst():"+llist.getFirst());

// (01) 将10添加到第一个位置。  返回true。
llist.offerFirst(10);
System.out.println("\nofferFirst(10):"+llist);

// (02) 将第一个元素删除。        失败的话,返回null。
System.out.println("llist.pollFirst():"+llist.pollFirst());
System.out.println("llist:"+llist);
// (03) 获取第一个元素。          失败的话,返回null。
System.out.println("llist.peekFirst():"+llist.peekFirst());

System.out.println("\n链表尾操作...");
// (01) 将20添加到最后一个位置。  失败的话,抛出异常!
llist.addLast(20);
System.out.println("addLast(20):"+llist);
// (02) 将最后一个元素删除。        失败的话,抛出异常!
System.out.println("llist.removeLast():"+llist.removeLast());
System.out.println("llist:"+llist);
// (03) 获取最后一个元素。          失败的话,抛出异常!
System.out.println("llist.getLast():"+llist.getLast());

// (01) 将20添加到第一个位置。  返回true。
llist.offerLast(20);
System.out.println("\nofferLast(20:"+llist);
// (02) 将第一个元素删除。        失败的话,返回null。
System.out.println("llist.pollLast():"+llist.pollLast());
System.out.println("llist:"+llist);
// (03) 获取第一个元素。          失败的话,返回null。
System.out.println("llist.peekLast():"+llist.peekLast());

// 将第3个元素设置300。不建议在LinkedList中使用此操作,因为效率低!
llist.set(2, 300);
System.out.println("\nset(2, 300):"+llist);

// ---- toArray(T[] a) ----
// 将LinkedList转行为数组arr
Integer arr[]=new Integer[llist.size()];
llist.toArray(arr);
System.out.print("llist.toArray(arr);");
for (Integer str:arr)
System.out.print(str+" ");
System.out.println();

// 输出大小
System.out.println("llist.size():"+llist.size());
// 清空LinkedList
llist.clear();
// 判断LinkedList是否为空
System.out.println("llist.isEmpty():"+llist.isEmpty()+"\n");

}

/**
* 将LinkedList当作 LIFO(后进先出)的堆栈
*/
private static void useLinkedListAsLIFO() {
System.out.println("\nuseLinkedListAsLIFO");
// 新建一个LinkedList
LinkedList stack = new LinkedList();

// 将1,2,3,4添加到堆栈中
stack.push("1");
stack.push("2");
stack.push("3");
stack.push("4");
// 打印“栈”
System.out.println("stack.push()"+stack);

// 删除“栈顶元素”
System.out.println("stack.pop():"+stack.pop());

// 打印“栈”
System.out.println(stack);

// 取出“栈顶元素”
System.out.println("stack.peek():"+stack.peek());

}

/**
* 将LinkedList当作 FIFO(先进先出)的队列
*/
private static void useLinkedListAsFIFO() {
System.out.println("\nuseLinkedListAsFIFO");
// 新建一个LinkedList
LinkedList queue = new LinkedList();

// 将10,20,30,40添加到队列。每次都是插入到末尾
queue.add("10");
queue.add("20");
queue.add("30");
queue.add("40");
// 打印“队列”
System.out.println("queue.add"+queue);

// 删除(队列的第一个元素)
System.out.println("queue.remove():"+queue.remove());

// 打印“队列”
System.out.println(queue);

// 读取(队列的第一个元素)
System.out.println("queue.element():"+queue.element());

}
}


输出:

[0, 1, 2, 3, 4]

llist.add(2, 5):[0, 1, 5, 2, 3, 4]

链表头操作…

addFirst(6):[6, 0, 1, 5, 2, 3, 4]

llist.removeFirst()返回:6

llist:[0, 1, 5, 2, 3, 4]

llist.getFirst():0

offerFirst(10):[10, 0, 1, 5, 2, 3, 4]

llist.pollFirst():10

llist:[0, 1, 5, 2, 3, 4]

llist.peekFirst():0

链表尾操作…

addLast(20):[0, 1, 5, 2, 3, 4, 20]

llist.removeLast():20

llist:[0, 1, 5, 2, 3, 4]

llist.getLast():4

offerLast(20:[0, 1, 5, 2, 3, 4, 20]

llist.pollLast():20

llist:[0, 1, 5, 2, 3, 4]

llist.peekLast():4

set(2, 300):[0, 1, 300, 2, 3, 4]

llist.toArray(arr);0 1 300 2 3 4

llist.size():6

llist.isEmpty():true

useLinkedListAsLIFO

stack.push()[4, 3, 2, 1]

stack.pop():4

[3, 2, 1]

stack.peek():3

useLinkedListAsFIFO

queue.add[10, 20, 30, 40]

queue.remove():10

[20, 30, 40]

queue.element():20

Vector

Vector简介

Vector 是矢量队列,它是JDK1.0版本添加的类。继承于AbstractList,实现了List, RandomAccess, Cloneable这些接口。

Vector 继承了AbstractList,实现了List;所以,它是一个队列,支持相关的添加、删除、修改、遍历等功能。

Vector 实现了RandmoAccess接口,即提供了随机访问功能。RandmoAccess是java中用来被List实现,为List提供快速访问功能的。在Vector中,我们即可以通过元素的序号快速获取元素对象;这就是快速随机访问。

Vector 实现了Cloneable接口,即实现clone()函数。它能被克隆。

和ArrayList不同,Vector中的操作是线程安全的。

Vector数据结构



Vector的数据结构和ArrayList差不多,它包含了3个成员变量:elementData , elementCount, capacityIncrement。

elementData 是”Object[]类型的数组”,它保存了添加到Vector中的元素。elementData是个动态数组,如果初始化Vector时,没指定动态数组的>大小,则使用默认大小10。随着Vector中元素的增加,Vector的容量也会动态增长,capacityIncrement是与容量增长相关的增长系数,具体的增长方式,请参考源码分析中的ensureCapacity()函数。

elementCount 是动态数组的实际大小。

capacityIncrement 是动态数组的增长系数。如果在创建Vector时,指定了capacityIncrement的大小;则,每次当Vector中动态数组容量增加时>,增加的大小都是capacityIncrement。

Vector构造函数

Vector共有4个构造函数
// 默认构造函数
Vector()

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

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

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




Vector的API

synchronized boolean        add(E object)//添加
void           add(int location, E object)

synchronized E              set(int location, E object)//设值

synchronized boolean        retainAll(Collection<?> collection)//保留下collection中含有的元素,适合求Vector的交集

int            indexOf(Object object)//查找元素
synchronized E              firstElement()   //获取第一个元素
E              get(int location)   //随机存取

synchronized int            capacity()
void           clear()
synchronized Object         clone()
boolean        contains(Object object)
synchronized boolean        containsAll(Collection<?> collection)
synchronized void           copyInto(Object[] elements)
synchronized E              elementAt(int location)
Enumeration<E> elements()

synchronized boolean        equals(Object object)

synchronized int            hashCode()
synchronized int            indexOf(Object object, int location)

synchronized void           insertElementAt(E object, int location)
synchronized boolean        isEmpty()
synchronized E              lastElement()
synchronized int            lastIndexOf(Object object, int location)
synchronized int            lastIndexOf(Object object)
synchronized E              remove(int location)
boolean        remove(Object object)
synchronized boolean        removeAll(Collection<?> collection)
synchronized void           removeAllElements()
synchronized boolean        removeElement(Object object)
synchronized void           removeElementAt(int location)

synchronized void           setElementAt(E object, int location)
synchronized void           setSize(int length)
synchronized int            size()
synchronized List<E>        subList(int start, int end)
synchronized <T> T[]        toArray(T[] contents)
synchronized Object[]       toArray()
synchronized String         toString()
synchronized void           trimToSize()


Vector源码分析

package java.util;

public class Vector<E>
extends AbstractList<E>
implements List<E>, RandomAccess, Cloneable, java.io.Serializable
{

// 保存Vector中数据的数组
protected Object[] elementData;

// 实际数据的数量
protected int elementCount;

// 容量增长系数
protected int capacityIncrement;

// Vector的序列版本号
private static final long serialVersionUID = -2767605614048989439L;

// Vector构造函数。默认容量是10。
public Vector() {
this(10);
}

// 指定Vector容量大小的构造函数
public Vector(int initialCapacity) {
this(initialCapacity, 0);
}

// 指定Vector"容量大小"和"增长系数"的构造函数
public Vector(int initialCapacity, int capacityIncrement) {
super();
if (initialCapacity < 0)
throw new IllegalArgumentException("Illegal Capacity: "+
initialCapacity);
// 新建一个数组,数组容量是initialCapacity
this.elementData = new Object[initialCapacity];
// 设置容量增长系数
this.capacityIncrement = capacityIncrement;
}

// 指定集合的Vector构造函数。
public Vector(Collection<? extends E> c) {
// 获取“集合(c)”的数组,并将其赋值给elementData
elementData = c.toArray();
// 设置数组长度
elementCount = elementData.length;
// c.toArray might (incorrectly) not return Object[] (see 6260652)
if (elementData.getClass() != Object[].class)
elementData = Arrays.copyOf(elementData, elementCount, Object[].class);
}

// 将数组Vector的全部元素都拷贝到数组anArray中
public synchronized void copyInto(Object[] anArray) {
System.arraycopy(elementData, 0, anArray, 0, elementCount);
}

// 将当前容量值设为 =实际元素个数
public synchronized void trimToSize() {
modCount++;
int oldCapacity = elementData.length;
if (elementCount < oldCapacity) {
elementData = Arrays.copyOf(elementData, elementCount);
}
}

// 确认“Vector容量”的帮助函数
private void ensureCapacityHelper(int minCapacity) {
int oldCapacity = elementData.length;
// 当Vector的容量不足以容纳当前的全部元素,增加容量大小。
// 若 容量增量系数>0(即capacityIncrement>0),则将容量增大当capacityIncrement
// 否则,将容量增大一倍。
if (minCapacity > oldCapacity) {
Object[] oldData = elementData;
int newCapacity = (capacityIncrement > 0) ?
(oldCapacity + capacityIncrement) : (oldCapacity * 2);
if (newCapacity < minCapacity) {
newCapacity = minCapacity;
}
elementData = Arrays.copyOf(elementData, newCapacity);
}
}

// 确定Vector的容量。
public synchronized void ensureCapacity(int minCapacity) {
// 将Vector的改变统计数+1
modCount++;
ensureCapacityHelper(minCapacity);
}

// 设置容量值为 newSize
public synchronized void setSize(int newSize) {
modCount++;
if (newSize > elementCount) {
// 若 "newSize 大于 Vector容量",则调整Vector的大小。
ensureCapacityHelper(newSize);
} else {
// 若 "newSize 小于/等于 Vector容量",则将newSize位置开始的元素都设置为null
for (int i = newSize ; i < elementCount ; i++) {
elementData[i] = null;
}
}
elementCount = newSize;
}

// 返回“Vector的总的容量”
public synchronized int capacity() {
return elementData.length;
}

// 返回“Vector的实际大小”,即Vector中元素个数
public synchronized int size() {
return elementCount;
}

// 判断Vector是否为空
public synchronized boolean isEmpty() {
return elementCount == 0;
}

// 返回“Vector中全部元素对应的Enumeration”
public Enumeration<E> elements() {
// 通过匿名类实现Enumeration
return new Enumeration<E>() {
int count = 0;

// 是否存在下一个元素
public boolean hasMoreElements() {
return count < elementCount;
}

// 获取下一个元素
public E nextElement() {
synchronized (Vector.this) {
if (count < elementCount) {
return (E)elementData[count++];
}
}
throw new NoSuchElementException("Vector Enumeration");
}
};
}

// 返回Vector中是否包含对象(o)
public boolean contains(Object o) {
return indexOf(o, 0) >= 0;
}

// 从index位置开始向后查找元素(o)。
// 若找到,则返回元素的索引值;否则,返回-1
public synchronized int indexOf(Object o, int index) {
if (o == null) {
// 若查找元素为null,则正向找出null元素,并返回它对应的序号
for (int i = index ; i < elementCount ; i++)
if (elementData[i]==null)
return i;
} else {
// 若查找元素不为null,则正向找出该元素,并返回它对应的序号
for (int i = index ; i < elementCount ; i++)
if (o.equals(elementData[i]))
return i;
}
return -1;
}

// 查找并返回元素(o)在Vector中的索引值
public int indexOf(Object o) {
return indexOf(o, 0);
}

// 从后向前查找元素(o)。并返回元素的索引
public synchronized int lastIndexOf(Object o) {
return lastIndexOf(o, elementCount-1);
}

// 从后向前查找元素(o)。开始位置是从前向后的第index个数;
// 若找到,则返回元素的“索引值”;否则,返回-1。
public synchronized int lastIndexOf(Object o, int index) {
if (index >= elementCount)
throw new IndexOutOfBoundsException(index + " >= "+ elementCount);

if (o == null) {
// 若查找元素为null,则反向找出null元素,并返回它对应的序号
for (int i = index; i >= 0; i--)
if (elementData[i]==null)
return i;
} else {
// 若查找元素不为null,则反向找出该元素,并返回它对应的序号
for (int i = index; i >= 0; i--)
if (o.equals(elementData[i]))
return i;
}
return -1;
}

// 返回Vector中index位置的元素。
// 若index月结,则抛出异常
public synchronized E elementAt(int index) {
if (index >= elementCount) {
throw new ArrayIndexOutOfBoundsException(index + " >= " + elementCount);
}

return (E)elementData[index];
}

// 获取Vector中的第一个元素。
// 若失败,则抛出异常!
public synchronized E firstElement() {
if (elementCount == 0) {
throw new NoSuchElementException();
}
return (E)elementData[0];
}

// 获取Vector中的最后一个元素。
// 若失败,则抛出异常!
public synchronized E lastElement() {
if (elementCount == 0) {
throw new NoSuchElementException();
}
return (E)elementData[elementCount - 1];
}

// 设置index位置的元素值为obj
public synchronized void setElementAt(E obj, int index) {
if (index >= elementCount) {
throw new ArrayIndexOutOfBoundsException(index + " >= " +
elementCount);
}
elementData[index] = obj;
}

// 删除index位置的元素
public synchronized void removeElementAt(int index) {
modCount++;
if (index >= elementCount) {
throw new ArrayIndexOutOfBoundsException(index + " >= " +
elementCount);
} else if (index < 0) {
throw new ArrayIndexOutOfBoundsException(index);
}

int j = elementCount - index - 1;
if (j > 0) {
System.arraycopy(elementData, index + 1, elementData, index, j);
}
elementCount--;
elementData[elementCount] = null; /* to let gc do its work */
}

// 在index位置处插入元素(obj)
public synchronized void insertElementAt(E obj, int index) {
modCount++;
if (index > elementCount) {
throw new ArrayIndexOutOfBoundsException(index
+ " > " + elementCount);
}
ensureCapacityHelper(elementCount + 1);
System.arraycopy(elementData, index, elementData, index + 1, elementCount - index);
elementData[index] = obj;
elementCount++;
}

// 将“元素obj”添加到Vector末尾
public synchronized void addElement(E obj) {
modCount++;
ensureCapacityHelper(elementCount + 1);
elementData[elementCount++] = obj;
}

// 在Vector中查找并删除元素obj。
// 成功的话,返回true;否则,返回false。
public synchronized boolean removeElement(Object obj) {
modCount++;
int i = indexOf(obj);
if (i >= 0) {
removeElementAt(i);
return true;
}
return false;
}

// 删除Vector中的全部元素
public synchronized void removeAllElements() {
modCount++;
// 将Vector中的全部元素设为null
for (int i = 0; i < elementCount; i++)
elementData[i] = null;

elementCount = 0;
}

// 克隆函数
public synchronized Object clone() {
try {
Vector<E> v = (Vector<E>) super.clone();
// 将当前Vector的全部元素拷贝到v中
v.elementData = Arrays.copyOf(elementData, elementCount);
v.modCount = 0;
return v;
} catch (CloneNotSupportedException e) {
// this shouldn't happen, since we are Cloneable
throw new InternalError();
}
}

// 返回Object数组
public synchronized Object[] toArray() {
return Arrays.copyOf(elementData, elementCount);
}

// 返回Vector的模板数组。所谓模板数组,即可以将T设为任意的数据类型
public synchronized <T> T[] toArray(T[] a) {
// 若数组a的大小 < Vector的元素个数;
// 则新建一个T[]数组,数组大小是“Vector的元素个数”,并将“Vector”全部拷贝到新数组中
if (a.length < elementCount)
return (T[]) Arrays.copyOf(elementData, elementCount, a.getClass());

// 若数组a的大小 >= Vector的元素个数;
// 则将Vector的全部元素都拷贝到数组a中。
System.arraycopy(elementData, 0, a, 0, elementCount);

if (a.length > elementCount)
a[elementCount] = null;

return a;
}

// 获取index位置的元素
public synchronized E get(int index) {
if (index >= elementCount)
throw new ArrayIndexOutOfBoundsException(index);

return (E)elementData[index];
}

// 设置index位置的值为element。并返回index位置的原始值
public synchronized E set(int index, E element) {
if (index >= elementCount)
throw new ArrayIndexOutOfBoundsException(index);

Object oldValue = elementData[index];
elementData[index] = element;
return (E)oldValue;
}

// 将“元素e”添加到Vector最后。
public synchronized boolean add(E e) {
modCount++;
ensureCapacityHelper(elementCount + 1);
elementData[elementCount++] = e;
return true;
}

// 删除Vector中的元素o
public boolean remove(Object o) {
return removeElement(o);
}

// 在index位置添加元素element
public void add(int index, E element) {
insertElementAt(element, index);
}

// 删除index位置的元素,并返回index位置的原始值
public synchronized E remove(int index) {
modCount++;
if (index >= elementCount)
throw new ArrayIndexOutOfBoundsException(index);
Object oldValue = elementData[index];

int numMoved = elementCount - index - 1;
if (numMoved > 0)
System.arraycopy(elementData, index+1, elementData, index,
numMoved);
elementData[--elementCount] = null; // Let gc do its work

return (E)oldValue;
}

// 清空Vector
public void clear() {
removeAllElements();
}

// 返回Vector是否包含集合c
public synchronized boolean containsAll(Collection<?> c) {
return super.containsAll(c);
}

// 将集合c添加到Vector中
public synchronized boolean addAll(Collection<? extends E> c) {
modCount++;
Object[] a = c.toArray();
int numNew = a.length;
ensureCapacityHelper(elementCount + numNew);
// 将集合c的全部元素拷贝到数组elementData中
System.arraycopy(a, 0, elementData, elementCount, numNew);
elementCount += numNew;
return numNew != 0;
}

// 删除集合c的全部元素
public synchronized boolean removeAll(Collection<?> c) {
return super.removeAll(c);
}

// 删除“非集合c中的元素”
public synchronized boolean retainAll(Collection<?> c)  {
return super.retainAll(c);
}

// 从index位置开始,将集合c添加到Vector中
public synchronized boolean addAll(int index, Collection<? extends E> c) {
modCount++;
if (index < 0 || index > elementCount)
throw new ArrayIndexOutOfBoundsException(index);

Object[] a = c.toArray();
int numNew = a.length;
ensureCapacityHelper(elementCount + numNew);

int numMoved = elementCount - index;
if (numMoved > 0)
System.arraycopy(elementData, index, elementData, index + numNew, numMoved);

System.arraycopy(a, 0, elementData, index, numNew);
elementCount += numNew;
return numNew != 0;
}

// 返回两个对象是否相等
public synchronized boolean equals(Object o) {
return super.equals(o);
}

// 计算哈希值
public synchronized int hashCode() {
return super.hashCode();
}

// 调用父类的toString()
public synchronized String toString() {
return super.toString();
}

// 获取Vector中fromIndex(包括)到toIndex(不包括)的子集
public synchronized List<E> subList(int fromIndex, int toIndex) {
return Collections.synchronizedList(super.subList(fromIndex, toIndex), this);
}

// 删除Vector中fromIndex到toIndex的元素
protected synchronized void removeRange(int fromIndex, int toIndex) {
modCount++;
int numMoved = elementCount - toIndex;
System.arraycopy(elementData, toIndex, elementData, fromIndex,
numMoved);

// Let gc do its work
int newElementCount = elementCount - (toIndex-fromIndex);
while (elementCount != newElementCount)
elementData[--elementCount] = null;
}

// java.io.Serializable的写入函数
private synchronized void writeObject(java.io.ObjectOutputStream s)
throws java.io.IOException {
s.defaultWriteObject();
}
}


Vector实际上是通过一个数组去保存数据的。当我们构造Vecotr时;若使用默认构造函数,则Vector的默认容量大小是10。

当Vector容量不足以容纳全部元素时,Vector的容量会增加。若容量增加系数 >0,则将容量的值增加“容量增加系数”;否则,将容量大小增加一倍。

Vector的克隆函数,即是将全部元素克隆到一个数组中。

Vector遍历方式

//第一种,随机访问,通过下标去遍历,速度最快,推荐
Integer value = null;
int size = vec.size();
for (int i=0; i<vec.size(); i++) {
value = (Integer)vec.get(i);
}

//第二种,另一种for循环。如下:

Integer value = null;
for (Integer integ:vec) {
value = integ;
}

//第三种:Enumeration遍历
Integer value = null;
Enumeration enu = vec.elements();
while (enu.hasMoreElements()) {
value = (Integer)enu.nextElement();
}


总结:遍历Vector,使用索引的随机访问方式最快,使用迭代器最慢。

实例

public class Test {
public static void main(String[] args) {
// 新建Vector
Vector<Integer> vec = new Vector<Integer>();

for(int i=0;i<5;i++)
vec.add(i);

System.out.println("vec.add():\n"+vec);

// 设置第一个元素为100
vec.set(0, 4);
System.out.println("vec.set(0, 4):"+vec);

// 将300插入到第3个位置
vec.add(2, 300);
System.out.println("vec.add(2, 300):"+vec);

// (顺序查找)获取100的索引
System.out.println("vec.indexOf(100):"+vec.indexOf(4));
// (倒序查找)获取100的索引
System.out.println("vec.lastIndexOf(100):"+vec.lastIndexOf(4));
// 获取第一个元素
System.out.println("vec.firstElement():"+vec.firstElement());
// 获取第3个元素
System.out.println("vec.elementAt(2):"+vec.elementAt(2));
// 获取最后一个元素
System.out.println("vec.lastElement():"+vec.lastElement());

// 获取Vector的大小
System.out.println("size:"+vec.size());
// 获取Vector的总的容量
System.out.println("capacity:"+vec.capacity());

// 获取vector的“第2”到“第4”个元素
System.out.println("vec.subList(1, 4):"+vec.subList(1, 4));

// 通过Enumeration遍历Vector
System.out.println("vec.get(i)遍历:");
for(int i=0;i<vec.size();i++)
System.out.print(vec.get(i)+" ");

Vector newVec = new Vector();
newVec.add(4);
newVec.add(300);

System.out.println("\n\nnewVec:"+newVec);

// 保留下与retainVec中元素相同的元素,其余的删除
System.out.println("vec.retain():"+vec.retainAll(newVec));
System.out.println("vec:"+vec);

// 获取vec对应的String数组
System.out.print("\nvec.toArray(arr):");
Integer[] arr=new Integer[vec.size()];
vec.toArray(arr);
for(Integer integ:arr)
System.out.print(integ+" ");

// 清空Vector。clear()和removeAllElements()一样!
vec.clear();
System.out.println("\nvec.clear()");
//        vec.removeAllElements();

// 判断Vector是否为空
System.out.println("vec.isEmpty():"+vec.isEmpty());
}
}


输出:

vec.add():

[0, 1, 2, 3, 4]

vec.set(0, 4):[4, 1, 2, 3, 4]

vec.add(2, 300):[4, 1, 300, 2, 3, 4]

vec.indexOf(100):0

vec.lastIndexOf(100):5

vec.firstElement():4

vec.elementAt(2):300

vec.lastElement():4

size:6

capacity:10

vec.subList(1, 4):[1, 300, 2]

vec.get(i)遍历:

4 1 300 2 3 4

newVec:[4, 300]

vec.retain():true

vec:[4, 300, 4]

vec.toArray(arr):4 300 4

vec.clear()

vec.isEmpty():true

Stack

Stack概述

Stack是栈。它的特性是:先进后出(FILO, First In Last Out)。

java有queue接口,但没有专门的实现,可以通过LinkedList实现队列

java工具包中的Stack是继承于Vector(矢量队列)的,由于Vector是通过数组实现的,这就意味着,Stack也是通过数组实现的,而非链表。当然,我们也可以将LinkedList当作栈来使用!

数据结构

java.lang.Object
↳     java.util.AbstractCollection<E>
↳     java.util.AbstractList<E>
↳     java.util.Vector<E>
↳     java.util.Stack<E>

public class Stack<E> extends Vector<E> {}




构造函数

Stack只有一个默认构造函数:

Stack stack = new Stack();


API

Stack是栈,它常用的API如下:

boolean       empty()
synchronized E             peek()
synchronized E             pop()
E             push(E object)
synchronized int           search(Object o)//查到返回下标,查不到返回-1


由于Stack和继承于Vector,因此它也包含Vector中的全部API。

源码分析

package java.util;

public
class Stack<E> extends Vector<E> {
// 版本ID。这个用于版本升级控制,这里不须理会!
private static final long serialVersionUID = 1224463164541339165L;

// 构造函数
public Stack() {
}

// push函数:将元素存入栈顶
public E push(E item) {
// 将元素存入栈顶。
// addElement()的实现在Vector.java中
addElement(item);

return item;
}

// pop函数:返回栈顶元素,并将其从栈中删除
public synchronized E pop() {
E    obj;
int    len = size();

obj = peek();
// 删除栈顶元素,removeElementAt()的实现在Vector.java中
removeElementAt(len - 1);

return obj;
}

// peek函数:返回栈顶元素,不执行删除操作
public synchronized E peek() {
int    len = size();

if (len == 0)
throw new EmptyStackException();
// 返回栈顶元素,elementAt()具体实现在Vector.java中
return elementAt(len - 1);
}

// 栈是否为空
public boolean empty() {
return size() == 0;
}

// 查找“元素o”在栈中的位置:由栈底向栈顶方向数
public synchronized int search(Object o) {
// 获取元素索引,elementAt()具体实现在Vector.java中
int i = lastIndexOf(o);

if (i >= 0) {
return size() - i;
}
return -1;
}
}


Stack实际上也是通过数组去实现的。

执行push时(即,将元素推入栈中),是通过将元素追加的数组的末尾中。

执行peek时(即,取出栈顶元素,不执行删除),是返回数组末尾的元素。

执行pop时(即,取出栈顶元素,并将该元素从栈中删除),是取出数组末尾的元素,然后将该元素从数组中删除。

Stack继承于Vector,意味着Vector拥有的属性和功能,Stack都拥有。

* Stack示例*

public static void main(String[] args) {
Stack<Integer> stack = new Stack<Integer>();
// 将1,2,3,4,5添加到栈中
for(int i=1; i<6; i++) {
stack.push(Integer.valueOf(i));
}
System.out.println(stack);

// 遍历并打印出该栈
iteratorThroughRandomAccess(stack) ;

// 查找在栈中的位置,并输出,查不到返回-1
int pos = stack.search(2);
System.out.println("the postion of 2 is:"+pos);

// pup栈顶元素之后,遍历栈
stack.pop();
//  通过Iterator去遍历Stack
iteratorThroughIterator(stack) ;

// peek栈顶元素之后,遍历栈
int val = stack.peek();
System.out.println("peek:"+val);
System.out.println(stack);

}

/**
* 通过快速访问遍历Stack
*/
public static void iteratorThroughRandomAccess(List list) {
int val;
for (int i=0; i<list.size(); i++) {
val = (int) list.get(i);
System.out.print(val+" ");
}
System.out.println();
}

/**
* 通过迭代器遍历Stack
*/
public static void iteratorThroughIterator(List list) {

int val;
for(Iterator iter = list.iterator(); iter.hasNext(); ) {
val = (int)iter.next();
System.out.print(val+" ");
}
System.out.println();
}


输出:

[1, 2, 3, 4, 5]

1 2 3 4 5

the postion of 2 is:4

1 2 3 4

peek:4

[1, 2, 3, 4]

List总结

List概括



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

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

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

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

ArrayList 是一个数组队列,相当于动态数组。它由数组实现,随机访问效率高,随机插入、随机删除效率低。   

LinkedList 是一个双向链表。它也可以被当作堆栈、队列或双端队列进行操作。LinkedList随机访问效率低,但随机插入、随机删除效率低。

Vector是矢量队列,和ArrayList一样,它也是一个动态数组,由数组实现。但是ArrayList是非线程安全的,而Vector是线程安全的。

Stack 是栈,它继承于Vector。它的特性是:先进后出(FILO, First In Last Out)。

List使用场景

学东西的最终目的是为了能够理解、使用它。下面先概括的说明一下各个List的使用场景,后面再分析原因。

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

1. 对于需要快速插入,删除元素,应该使用LinkedList。

2. 对于需要快速随机访问元素,应该使用ArrayList。

3. 对于“单线程环境” 或者 “多线程环境,但List仅仅只会被单个线程操作”,此时应该使用非同步的类(如:ArrayList)。

对于“多线程环境,且List可能同时被多个线程操作”,此时,应该使用同步的类(如Vector)。

* LinkedList和ArrayList性能差异分析*

插入元素速率分析

下面我们看看为什么LinkedList中插入元素很快,而ArrayList中插入元素很慢!

LinkedList.java中向指定位置插入元素的代码如下:

// 在index前添加节点,且节点的值为element
public void add(int index, E element) {
addBefore(element, (index==size ? header : entry(index)));
}

// 获取双向链表中指定位置的节点
private Entry<E> entry(int index) {
if (index < 0 || index >= size)
throw new IndexOutOfBoundsException("Index: "+index+
", Size: "+size);
Entry<E> e = header;
// 获取index处的节点。
// 若index < 双向链表长度的1/2,则从前向后查找;
// 否则,从后向前查找。
if (index < (size >> 1)) {
for (int i = 0; i <= index; i++)
e = e.next;
} else {
for (int i = size; i > index; i--)
e = e.previous;
}
return e;
}

// 将节点(节点数据是e)添加到entry节点之前。
private Entry<E> addBefore(E e, Entry<E> entry) {
// 新建节点newEntry,将newEntry插入到节点e之前;并且设置newEntry的数据是e
Entry<E> newEntry = new Entry<E>(e, entry, entry.previous);
// 插入newEntry到链表中
newEntry.previous.next = newEntry;
newEntry.next.previous = newEntry;
size++;
modCount++;
return newEntry;
}


从中,我们可以看出:通过add(int index, E element)向LinkedList插入元素时。先是在双向链表中找到要插入节点的位置index;找到之后,再插入一个新节点。

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

接着,我们看看ArrayList.java中向指定位置插入元素的代码。如下

// 将e添加到ArrayList的指定位置
public void add(int index, E element) {
if (index > size || index < 0)
throw new IndexOutOfBoundsException(
"Index: "+index+", Size: "+size);

ensureCapacity(size+1);  // Increments modCount!!
System.arraycopy(elementData, index, elementData, index + 1,
size - index);
elementData[index] = element;
size++;
}


ensureCapacity(size+1) 的作用是“确认ArrayList的容量,若容量不够,则增加容量。”

真正耗时的操作是 System.arraycopy(elementData, index, elementData, index + 1, size - index);

Sun JDK包的java/lang/System.java中的arraycopy()声明如下:

public static native void arraycopy(Object src, int srcPos, Object dest, int destPos, int length);


arraycopy()是个JNI函数,它是在JVM中实现的。sunJDK中看不到源码,不过可以在OpenJDK包中看到的源码。网上有对arraycopy()的分析说明.

实际上,我们只需要了解: System.arraycopy(elementData, index, elementData, index + 1, size - index); 会移动index之后所有元素即可。这就意味着,ArrayList的add(int index, E element)函数,会引起index之后所有元素的改变!

通过上面的分析,我们就能理解为什么LinkedList中插入元素很快,而ArrayList中插入元素很慢。“删除元素”与“插入元素”的原理类似,这里就不再过多说明。

随机访问速率分析

接下来,我们看看 “为什么LinkedList中随机访问很慢,而ArrayList中随机访问很快”。

// 返回LinkedList指定位置的元素
public E get(int index) {
return entry(index).element;
}

// 获取双向链表中指定位置的节点
private Entry<E> entry(int index) {
if (index < 0 || index >= size)
throw new IndexOutOfBoundsException("Index: "+index+
", Size: "+size);
Entry<E> e = header;
// 获取index处的节点。
// 若index < 双向链表长度的1/2,则从前先后查找;
// 否则,从后向前查找。
if (index < (size >> 1)) {
for (int i = 0; i <= index; i++)
e = e.next;
} else {
for (int i = size; i > index; i--)
e = e.previous;
}
return e;
}


从中,我们可以看出:通过get(int index)获取LinkedList第index个元素时。先是在双向链表中找到要index位置的元素;找到之后再返回。

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

下面看看ArrayList随机访问的代码

// 获取index位置的元素值
public E get(int index) {
RangeCheck(index);

return (E) elementData[index];
}

private void RangeCheck(int index) {
if (index >= size)
throw new IndexOutOfBoundsException(
"Index: "+index+", Size: "+size);
}


从中,我们可以看出:通过get(int index)获取ArrayList第index个元素时。直接返回数组中index位置的元素,而不需要像LinkedList一样进行查找。

Vector和ArrayList比较

相同之处

1 它们都是List

它们都继承于AbstractList,并且实现List接口。

ArrayList和Vector的类定义如下:

// ArrayList的定义
public class ArrayList<E> extends AbstractList<E>
implements List<E>, RandomAccess, Cloneable, java.io.Serializable

// Vector的定义
public class Vector<E> extends AbstractList<E>
implements List<E>, RandomAccess, Cloneable, java.io.Serializable {}


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

实现RandomAccess接口,意味着它们都支持快速随机访问;

实现Cloneable接口,意味着它们能克隆自己。

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

ArrayList.java中定义数组elementData用于保存元素

// 保存ArrayList中数据的数组
private transient Object[] elementData;


Vector.java中也定义了数组elementData用于保存元素

// 保存Vector中数据的数组
protected Object[] elementData;


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

若创建ArrayList或Vector时,没指定容量大小;则使用默认容量大小10。

ArrayList的默认构造函数如下:

/ ArrayList构造函数。默认容量是10。
public ArrayList() {
this(10);
}


Vector的默认构造函数如下:

// Vector构造函数。默认容量是10。
public Vector() {
this(10);
}


5 它们都支持Iterator和listIterator遍历

它们都继承于AbstractList,而AbstractList中分别实现了 “iterator()接口返回Iterator迭代器” 和 “listIterator()返回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”。

ArrayList中容量增长的主要函数如下:

public void ensureCapacity(int minCapacity) {
// 将“修改统计数”+1
modCount++;
int oldCapacity = elementData.length;
// 若当前容量不足以容纳当前的元素个数,设置 新的容量=“(原始容量x3)/2 + 1”
if (minCapacity > oldCapacity) {
Object oldData[] = elementData;
int newCapacity = (oldCapacity * 3)/2 + 1;
if (newCapacity < minCapacity)
newCapacity = minCapacity;
elementData = Arrays.copyOf(elementData, newCapacity);
}
}


Vector中容量增长的主要函数如下:

private void ensureCapacityHelper(int minCapacity) {
int oldCapacity = elementData.length;
// 当Vector的容量不足以容纳当前的全部元素,增加容量大小。
// 若 容量增量系数>0(即capacityIncrement>0),则将容量增大当capacityIncrement
// 否则,将容量增大一倍。
if (minCapacity > oldCapacity) {
Object[] oldData = elementData;
int newCapacity = (capacityIncrement > 0) ?
(oldCapacity + capacityIncrement) : (oldCapacity * 2);
if (newCapacity < minCapacity) {
newCapacity = minCapacity;
}
elementData = Arrays.copyOf(elementData, newCapacity);
}
}


5 对Enumeration的支持不同。

Vector支持通过Enumeration去遍历,而List不支持

Vector中实现Enumeration的代码如下:

public Enumeration<E> elements() {
// 通过匿名类实现Enumeration
return new Enumeration<E>() {
int count = 0;

// 是否存在下一个元素
public boolean hasMoreElements() {
return count < elementCount;
}

// 获取下一个元素
public E nextElement() {
synchronized (Vector.this) {
if (count < elementCount) {
return (E)elementData[count++];
}
}
throw new NoSuchElementException("Vector Enumeration");
}
};
}


转载/article/4709041.html
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: