首先分析一下集合与数组的区别:1.java中的数组一般用于存储基本数据类型,而且是静态的,即长度固定不变,这就不适用于元素个数未知的情况;2.集合只能用于存储引用类型,并且长度可变,适用于大多数情况,可用toArray()方法转换成数组。

java语言提供了多种集合类的接口,如List、Set、Map等。其中,List接口继承自Collection,它的实现类有ArrayList、LinkedList、Vector(Stack),下面就从它们的源代码开始:

1.ArrayList(数组列表)

顾名思义,这是一种以数组形式进行存储的列表,所以其优点是便于随机访问,而在插入和删除操作时效率较低。

构造方法(三种):

1.public ArrayList(int initialCapacity)  指定初始列表的容量,当容量不够时会自动进行扩容

2.public ArrayList()  空的构造方法

3.public ArrayList(Collection extends E> c)  初始化列表元素,传入参数为一个集合类的对象

java list下标 java list addall_Code

java list下标 java list addall_Code_02

1 ArrayList arrayList1 = new ArrayList(3); //初始化ArrayList容量大小

2 arrayList1.add("A");3 arrayList1.add("B");4 arrayList1.add("C");5 ArrayList arrayList2 = new ArrayList(arrayList1); //初始化ArrayList元素

6 System.out.println(arrayList2); //[A, B, C]

View Code

插入元素(add)

1.在列表尾部插入 add(E e)

java list下标 java list addall_Code

java list下标 java list addall_Code_02

1 public booleanadd(E e) {2 ensureCapacityInternal(size + 1); //Increments modCount!!

3 elementData[size++] =e;4 return true;5 }

View Code

2.在列表指定位置插入 add(int index, E element)

java list下标 java list addall_Code

java list下标 java list addall_Code_02

1 public void add(intindex, E element) {2 rangeCheckForAdd(index);3

4 ensureCapacityInternal(size + 1); //Increments modCount!!

5 System.arraycopy(elementData, index, elementData, index + 1,6 size -index);7 elementData[index] =element;8 size++;9 }

View Code

3.在列表尾部插入一个子集 addAll(Collection extends E> c)

java list下标 java list addall_Code

java list下标 java list addall_Code_02

1 public boolean addAll(Collection extends E>c) {2 Object[] a =c.toArray();3 int numNew =a.length;4 ensureCapacityInternal(size + numNew); //Increments modCount

5 System.arraycopy(a, 0, elementData, size, numNew);6 size +=numNew;7 return numNew != 0;8 }

View Code

4.在列表的指定位置插入一个子集 addAll(int index, Collection extends E> c)

java list下标 java list addall_Code

java list下标 java list addall_Code_02

1 public boolean addAll(int index, Collection extends E>c) {2 rangeCheckForAdd(index);3

4 Object[] a =c.toArray();5 int numNew =a.length;6 ensureCapacityInternal(size + numNew); //Increments modCount

7

8 int numMoved = size -index;9 if (numMoved > 0)10 System.arraycopy(elementData, index, elementData, index +numNew,11 numMoved);12

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

View Code

观察源码可知,在指定位置插入元素其实是通过arraycopy()方法来实现的,即是将原数组复制到目标数组,因而效率较低。

应用示例:

java list下标 java list addall_Code

java list下标 java list addall_Code_02

1 ArrayList arrayList1 = new ArrayList(3); //初始化ArrayList容量大小

2 arrayList1.add("A");3 arrayList1.add("B");4 arrayList1.add("C");5 arrayList1.add("D");6 System.out.println(arrayList1); //[A, B, C, D]

7 arrayList1.add(0, "E");8 System.out.println(arrayList1); //[E, A, B, C, D]

View Code

查找元素

1.查找指定位置的元素 get(int index)

2.查找指定元素的位置 indexOf(Object o)、lastIndexOf(Object o)

3.查找列表中是否包含指定元素 contains(Object o)

java list下标 java list addall_Code

java list下标 java list addall_Code_02

1 public booleancontains(Object o) {2 return indexOf(o) >= 0;3 }

View Code

由于ArrayList以数组方式实现,自带索引,所以便于随机查找。

修改元素

修改指定位置的元素 set(int index, E element)

java list下标 java list addall_Code

java list下标 java list addall_Code_02

1 ArrayList arrayList1 = new ArrayList(3); //初始化ArrayList容量大小

2 arrayList1.add("A");3 arrayList1.add("B");4 arrayList1.add("C");5 arrayList1.add("D");6 System.out.println(arrayList1); //[A, B, C, D]

7 arrayList1.set(0, "X");8 System.out.println(arrayList1); //[X, B, C, D]

View Code

由于ArrayList以数组方式实现,自带索引,所以便于随机修改。

删除元素

1.删除指定位置的元素 remove(int index)

java list下标 java list addall_Code

java list下标 java list addall_Code_02

1 public E remove(intindex) {2 rangeCheck(index);3

4 modCount++;5 E oldValue =elementData(index);6

7 int numMoved = size - index - 1;8 if (numMoved > 0)9 System.arraycopy(elementData, index+1, elementData, index,10 numMoved);11 elementData[--size] = null; //clear to let GC do its work

12

13 returnoldValue;14 }

View Code

2.删除指定元素 remove(Object o)

java list下标 java list addall_Code

java list下标 java list addall_Code_02

1 public booleanremove(Object o) {2 if (o == null) {3 for (int index = 0; index < size; index++)4 if (elementData[index] == null) {5 fastRemove(index);6 return true;7 }8 } else{9 for (int index = 0; index < size; index++)10 if(o.equals(elementData[index])) {11 fastRemove(index);12 return true;13 }14 }15 return false;16 }

View Code

3.清空列表 clear()

java list下标 java list addall_Code

java list下标 java list addall_Code_02

1 public voidclear() {2 modCount++;3

4 //clear to let GC do its work

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

8 size = 0;9 }

View Code

从源码中我们可以知道,删除元素时也是通过arraycopy()方法,将原数组复制到目标数组,因而效率较低。

应用示例:

java list下标 java list addall_Code

java list下标 java list addall_Code_02

1 ArrayList arrayList1 = new ArrayList(3); //初始化ArrayList容量大小

2 arrayList1.add("A");3 arrayList1.add("B");4 arrayList1.add("C");5 arrayList1.add("D");6 arrayList1.remove(0);7 System.out.println(arrayList1); //[B, C, D]

8 arrayList1.remove("D");9 System.out.println(arrayList1); //[B, C]

10 arrayList1.clear();11 System.out.println(arrayList1.isEmpty()); //true

View Code

2.LinkedList(链接列表)

顾名思义,以链表的方式来实现List接口,其优点是便于元素插入和删除,而在随机访问时效率较低。此外LinkedList提供额外的get,remove,insert方法操作 LinkedList的首部或尾部。这些操作使LinkedList可被用作堆栈(stack),队列(queue)或双向队列(deque)。

存储节点的基本定义(静态内部类实现)

java list下标 java list addall_Code

java list下标 java list addall_Code_02

1 private static class Node{2 E item;3 Nodenext;4 Nodeprev;5

6 Node(Node prev, E element, Nodenext) {7 this.item =element;8 this.next =next;9 this.prev =prev;10 }11 }

View Code

构造方法(两种)

1. public LinkedList()  空的构造方法

2.public LinkedList(Collection extends E> c)  初始化列表元素,传入参数为一个集合类的对象

插入元素

1.addFirst(E e) 在列表的头部插入

2.addLast(E e)、add(E e) 在列表的尾部插入

3.add(int index, E element) 在列表的指定位置插入

4.addAll(Collection extends E> c) 在列表的尾部插入一个子集

5.addAll(int index, Collection extends E> c) 在列表的指定位置插入一个子集

应用示例:

java list下标 java list addall_Code

java list下标 java list addall_Code_02

1 LinkedList linkedList = new LinkedList();2 LinkedList linkedList2 = new LinkedList();3 linkedList.add(100);4 linkedList.add(120);5 linkedList.add(105);6 System.out.println(linkedList);//[100, 120, 105]

7 linkedList.add(200);8 System.out.println(linkedList);//[100, 120, 105, 200]

9 linkedList.add(0, 300);10 System.out.println(linkedList);//[300, 100, 120, 105, 200]

11 linkedList.addFirst(400);12 System.out.println(linkedList);//[400, 300, 100, 120, 105, 200]

13 linkedList.addLast(500);14 System.out.println(linkedList);//[400, 300, 100, 120, 105, 200, 500]

15

16 linkedList2.addAll(linkedList);17 System.out.println(linkedList2);//[400, 300, 100, 120, 105, 200, 500]

18 linkedList2.addAll(0, linkedList);19 System.out.println(linkedList2);//[400, 300, 100, 120, 105, 200, 500, 400, 300, 100, 120, 105, 200, 500]

View Code

由于LinkedList以链表方式实现,所以在插入元素时只需要修改指针(前驱节点和后继节点)即可,因而效率较高。

查找元素

1.getFirst() 返回列表头部元素

2.getLast() 返回列表尾部元素

3.get(int index) 返回列表指定位置的元素

4.indexOf(Object o) 返回指定元素首次出现的位置

5.lastIndexOf(Object o) 返回指定元素最后一次出现的位置

应用示例:

java list下标 java list addall_Code

java list下标 java list addall_Code_02

1 System.out.println(linkedList);//[400, 300, 100, 120, 105, 200, 500]

2 System.out.println(linkedList.getFirst());//400

3 System.out.println(linkedList.getLast());//500

4 System.out.println(linkedList.get(3));//120

5 System.out.println(linkedList.indexOf(120));//3;

6 System.out.println(linkedList.lastIndexOf(120));//3

View Code

由于链表实现的列表没有索引,所以查找指定位置的元素只能通过不断遍历来实现,因而效率低下。

修改元素

1.set(int index, E element) 修改指定位置的元素

java list下标 java list addall_Code

java list下标 java list addall_Code_02

1 public E set(intindex, E element) {2 checkElementIndex(index);3 Node x =node(index);4 E oldVal =x.item;5 x.item =element;6 returnoldVal;7 }

View Code

同样首先需要遍历找到指定元素,然后进行修改,效率低下。

删除元素

1.removeFirst() 删除列表头部元素

2.removeLast() 删除列表尾部元素

3.remove(Object o) 删除指定元素

4.remove(int index) 删除指定位置的元素

应用示例:

java list下标 java list addall_Code

java list下标 java list addall_Code_02

1 System.out.println(linkedList);//[400, 300, 100, 120, 105, 200, 500]

2 System.out.println(linkedList.removeFirst());//400

3 System.out.println(linkedList.removeLast());//500

4 System.out.println(linkedList.remove(3));//105

5 System.out.println(linkedList.remove(new Integer("300")));//true

View Code

由于链接的实现方式,删除元素只需要修改指针(前驱节点和后继节点)即可,因而效率较高。

3.Vector(Stack)向量

Vector与ArrayList用法类似,并且也是以数组方式实现的,但它消耗的内存资源比ArrayList多,因而常常用于大量数据的存储,并且Vector是线程安全的。Stack(栈)是Vector的一个子类,具有后进先出的特性。

构造方法(四种)

1.Vector(int initialCapacity, int capacityIncrement) 指定初始容量以及扩容的大小

java list下标 java list addall_Code

java list下标 java list addall_Code_02

1 public Vector(int initialCapacity, intcapacityIncrement) {2 super();3 if (initialCapacity < 0)4 throw new IllegalArgumentException("Illegal Capacity: "+

5 initialCapacity);6 this.elementData = newObject[initialCapacity];7 this.capacityIncrement =capacityIncrement;8 }

View Code

2.Vector(int initialCapacity) 指定初始容量

3.Vector() 空的构造器

4.Vector(Collection extends E> c) 初始化向量元素,参数为一个集合类的对象

应用示例:

java list下标 java list addall_Code

java list下标 java list addall_Code_02

1 Vector vector1 = new Vector();2 vector1.add(100);3 vector1.add(102);4 Vector vector2 = new Vector(6);5 Vector vector3 = new Vector(6, 3);6 Vector vector4 = new Vector(vector1);7 System.out.println(vector4); //[100, 102]

View Code

插入元素

1.addElement(E obj)、add(E e) 在向量尾部插入指定元素

2.add(int index, E element)、insertElementAt(E obj, int index) 在指定位置插入元素

java list下标 java list addall_Code

java list下标 java list addall_Code_02

1 public synchronized void insertElementAt(E obj, intindex) {2 modCount++;3 if (index >elementCount) {4 throw newArrayIndexOutOfBoundsException(index5 + " > " +elementCount);6 }7 ensureCapacityHelper(elementCount + 1);8 System.arraycopy(elementData, index, elementData, index + 1, elementCount -index);9 elementData[index] =obj;10 elementCount++;11 }

View Code

3.addAll(Collection extends E> c) 在向量尾部插入一个子集

4.addAll(int index, Collection extends E> c) 在向量的指定位置插入一个子集

java list下标 java list addall_Code

java list下标 java list addall_Code_02

1 public synchronized boolean addAll(int index, Collection extends E>c) {2 modCount++;3 if (index < 0 || index >elementCount)4 throw newArrayIndexOutOfBoundsException(index);5

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

10 int numMoved = elementCount -index;11 if (numMoved > 0)12 System.arraycopy(elementData, index, elementData, index +numNew,13 numMoved);14

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

View Code

与ArrayList类似,在指定位置插入是通过arraycopy()方法实现的,即是将原数组复制到目标数组,因而效率较低。

将泛型参数类型设置为Object,就可以插入不同类型的数据:

1 Vector vec = new Vector<>();2 vec.add(100);3 vec.add(new Integer(120));4 vec.add("hello");5 vec.add(true);6 System.out.println(vec);//[100, 120, hello, true]7 //若要还原向量中的元素类型,需要进行强制类型转换

8 System.out.println((int)vec.get(1)+100);//220

9 System.out.println(100+(int)vec.get(0));//200

查询元素

1.contains(Object o) 查询是否包含指定元素

2.indexOf(Object o) 返回指定元素首次出现的位置

3.indexOf(Object o, int index) 返回从index开始的指定元素首次出现的位置

4.elementAt(int index) 返回指定位置的元素

5.firstElement() 返回响向量的第一个元素

6.lastElement() 返回向量的最后一个元素

7.get(int index) 返回指定位置的元素

8.subList(int fromIndex, int toIndex) 返回指定位置的子序列

由于Vector使用数组实现,自带索引,因此在查询时效率较高。

修改元素

1.set(int index, E element) 修改指定位置的元素

2.setElementAt(E obj, int index) 修改指定位置的元素

应用示例:

java list下标 java list addall_Code

java list下标 java list addall_Code_02

1 System.out.println(vector4); //[100, 102, 200]

2

3 vector4.set(0, 500);4 System.out.println(vector4);//[500, 102, 200]

5 vector4.setElementAt(300, 1);6 System.out.println(vector4);//[500, 300, 200]

View Code

删除元素

1.removeElement(Object obj)、remove(Object o) 删除首次出现的指定元素

2.removeAllElements() 清空向量的所有元素

3.remove(int index) 删除指定位置的元素

4.removeAll(Collection> c) 删除向量中出现的集合c中的元素

5.removeElementAt(int index) 删除指定位置的元素

应用示例:

java list下标 java list addall_Code

java list下标 java list addall_Code_02

1 System.out.println(vector4);//[500, 300, 200]

2

3 vector4.removeAll(vector1);4 System.out.println(vector4);//[500, 300]

5 vector4.removeAllElements();

View Code

与ArrayList类似,删除指定位置的元素时也是将原数组复制到目标数组实现的。

Stack(栈)

前面说过Stack是Vector的一个子类,可以调用其父类的大部分成员方法,这里只介绍Stack自身的一些成员方法:

1.public Stack() 空的构造器

2.E push(E item) 将一个元素压入栈顶

3.E pop() 返回栈顶元素,并将该元素移除

4.E peek() 返回栈顶元素,而并不将其移除

5.empty() 判断栈是否为空

6.search(Object o) 搜索栈中的元素,返回值为该元素在栈中的位置(从1开始计数,自上而下)

java list下标 java list addall_Code

java list下标 java list addall_Code_02

1 Stack stack = new Stack();2 stack.push(100);3 stack.push(200);4 stack.push(300);5 System.out.println(stack.peek());//300

6 System.out.println(stack.size());//3

7 System.out.println(stack.pop());//300

8 System.out.println(stack.size());//2

9 stack.push(100);10 stack.push(200);11 stack.push(300);12 System.out.println(stack);//[100, 200, 100, 200, 300]

13 System.out.println(stack.search(100));//3

View Code

至此,List集合的几个实现类基本介绍完毕,下一节将分析这几个实现类的区别。