上篇總結了Set集合,這回總結下List集合。。。。先來框架圖:
一、List集合
List集合代表一個元素有序,可重復的集合,集合中每個元素都有對應的順序索引。List接口中增加了一些根據索引操作元素的方法:
void add(int index,E element ) 在列表的指定位置插入該元素。
boolean addAll(int index,Collection c) 將集合c包含的所有元素都插入到List集合的index處。
Object get(int index) 返回集合index索引出的元素。
。。。。。詳見
1.ListIterator接口:List額外提供的一個listIterator()方法,提供了專門操作List的方法。
ListIterator接口在Iterator的基礎上增加了如下方法:
boolean hasPrevious(): 返回該迭代器關聯的集合是否還有上一個元素。
Object previous(): 返回該迭代器的上一個元素。
void add((E e): 在指定位置插入一個元素。
示例:
import java.util.*; public class TestListIterator { public static void main(String[] args) { String[] books = { "我是帥哥", "帥哥是我" }; List bookList = new ArrayList(); for (int i = 0; i < books.length ; i++ ) { bookList.add(books[i]); } ListIterator lit = bookList.listIterator(); while (lit.hasNext()) { System.out.println(lit.next()); lit.add("-------分隔符-------"); //加入一個元素 } System.out.println("==========下面開始反向迭代==========="); while(lit.hasPrevious()) { System.out.println(lit.previous()); } } }
輸出結果:
我是帥哥
帥哥是我
==========下面開始反向迭代===========
-------分隔符-------
帥哥是我
-------分隔符-------
我是帥哥
輸出完成 (耗時 0 秒) - 正常終止
2.ArrayList實現類和Vector實現類:
ArrayList和Vector是基於數組實現的list類,所以ArrayList和Vector封裝了一個動態的,允許再分配的Object[]數組,不指定的話長度默認為10。ArrayList和Vector對象使用initialCapacity參數來設置該數組的長度,當向集合添加大量元素時,可以使用ensureCapac(int minCapacity)方法一次性的增加initialCapacity。
ArrayList和Vector在用法上幾乎完全相同,但Vector比較古老,方法名比較長,最好是不使用。ArrayList是線程不安全的,Vector是線程安全的,但這個完全可以手動將一個ArrayList變成線程安全的。
ArrayList示例:
import java.util.*; public class TestList { public static void main(String[] args) { List books = new ArrayList(); //向books集合中添加三個元素 books.add(new String("輕量級J2EE企業應用實戰")); books.add(new String("Struts2權威指南")); books.add(new String("基於J2EE的Ajax寶典")); System.out.println(books); //將新字符串對象插入在第二個位置 books.add(1 , new String("ROR敏捷開發最佳實踐"));//add是插入,插入到當前位置,當前的元素向后退,並沒有覆蓋! for (int i = 0 ; i < books.size() ; i++ ) { System.out.println(books.get(i)); } System.out.println("size:"+books.size()); //刪除第三個元素 books.remove(2); System.out.println(books); //判斷指定元素在List集合中位置:輸出1,表明位於第二位 System.out.println(books.indexOf(new String("ROR敏捷開發最佳實踐")));//1 //將第二個元素替換成新的字符串對象 books.set(1, new String("Struts2權威指南")); System.out.println(books); //將books集合的第二個元素(包括)到第三個元素(不包括)截取稱子集合 System.out.println(books.subList(1 , 2)); } }
輸出結果:
---------- java運行 ----------
[輕量級J2EE企業應用實戰, Struts2權威指南, 基於J2EE的Ajax寶典]
輕量級J2EE企業應用實戰
ROR敏捷開發最佳實踐
Struts2權威指南
基於J2EE的Ajax寶典
size:4
[輕量級J2EE企業應用實戰, ROR敏捷開發最佳實踐, 基於J2EE的Ajax寶典]
1
[輕量級J2EE企業應用實戰, Struts2權威指南, 基於J2EE的Ajax寶典]
[Struts2權威指南]
輸出完成 (耗時 0 秒) - 正常終止
二、Queue集合
Queue用於模擬隊列這種數據結構,先進先出。
Queue接口定義的方法如下:
boolean add(E e): 將指定的元素插入此隊列(如果立即可行且不會違反容量限制),在成功時返回 true,如果當前沒有可用的空間,則拋出 IllegalStateException。
E element(): 獲取隊列頭部元素,但不刪除該元素。
boolean offer(E e): 將指定的元素插入此隊列,當使用有容量限制的隊列時,此方法通常要優於 add(E)。
E peek(): 獲取但不移除此隊列的頭;如果此隊列為空,則返回 null。
E poll(): 獲取並移除此隊列的頭,如果此隊列為空,則返回 null。
E remove(): 獲取並移除此隊列的頭。
1.PriorityQueue實現類
PriorityQueue是一個比較標准的隊列實現類,之所以說比較標准,而不是絕對標准,是因為PriorityQueue保存隊列元素的順序並不是按加入隊列的順序,而是按隊列元素的大小進行重新排序。
示例:
import java.util.*; public class TestPriorityQueue { public static void main(String[] args) { PriorityQueue pq = new PriorityQueue(); //下面代碼依次向pq中加入四個元素 pq.offer(6); pq.offer(-3); pq.offer(9); pq.offer(0); //輸出pq隊列,並不是按元素的加入順序排列,而是按元素的大小順序排列 System.out.println(pq); //訪問隊列第一個元素,其實就是隊列中最小的元素:-3 System.out.println(pq.peek()); } }
輸出結果:
---------- java運行 ----------
[-3, 0, 9, 6]
-3
輸出完成 (耗時 0 秒) - 正常終止
2.Deque接口與ArrayQueue實現類
Deque接口是Queue接口的子接口,它代表一個雙端隊列,Deque接口里定義了一些雙端隊列的方法,允許從兩端來操作隊列的元素。
Void addFirst(Object e):將指定元素插入該雙端隊列的開頭。
Void addLast(Object e):將指定隊列插入該雙端隊列的末尾。
Iterator descendingIterator():返回該雙端隊列對應的迭代器,該迭代器將以逆向順序來迭代隊列中的元素。
Object getFirst(): 獲取但不刪除隊列的第一個元素。
詳細參考api
ArrayQueue是Deque接口的典型實現類,他是一個基於數組實現的雙端隊列,底部也是采用動態的、可重新分配的Object[]數組存儲集合元素。
示例:把ArrayQueue當”棧“使用
import java.util.*; public class ArrayDequeTest { public static void main(String[] args) { ArrayDeque stack = new ArrayDeque(); //依次將三個元素push入棧 stack.push("java"); stack.push("java EE"); stack.push("Android"); System.out.println(stack); //輸出 //訪問第一個元素,但不將其pop出棧 System.out.println(stack.peek());// // System.out.println(stack); //pop出第一個元素 System.out.println(stack.pop()); // System.out.println(stack); } }
輸出結果:
[Android, java EE, java]
Android
[Android, java EE, java]
Android
[java EE, java]
**在現在的程序中需要使用“棧”這種數據結構時,推薦使用ArrayDeque或LinkedList,而不是Stack。
3.LinkedList實現類
LinkedList實現了List接口和Deque接口(好像圖上沒有畫出來。。。。。),因此他是一個List集合還可以被當成雙端隊列來使用。
LinkedList與ArrayList,ArrayDeque的實現機制完全不同,ArrayList、ArrayDeque內部以數組的形式來保存集合中的元素,因此隨機訪問集合元素時有較好的性能;而LinkedList內部以鏈表的形式來保存集合中的元素,因此隨機訪問性能較差,但是插入、刪除元素時非常快。
示例:
import java.util.*; public class TestLinkedList { public static void main(String[] args) { LinkedList books = new LinkedList(); //將字符串元素加入隊列的尾部 books.offer("Java"); //將一個字符串元素入棧 books.push("J2EE"); //將字符串元素添加到隊列的頭部 books.offerFirst("Android"); for (int i = 0; i < books.size() ; i++ ) { System.out.println(books.get(i)); } //訪問、並不刪除隊列的第一個元素 System.out.println(books.peekFirst()); //訪問、並不刪除隊列的最后一個元素 System.out.println(books.peekLast()); //采用出棧的方式將第一個元素pop出隊列 System.out.println(books.pop()); //下面輸出將看到隊列中第一個元素被刪除 System.out.println(books); //訪問、並刪除隊列的最后一個元素 System.out.println(books.pollLast()); //下面輸出將看到隊列中只剩下中間一個元素:輕量級J2EE企業應用實戰 System.out.println(books); } }
輸出結果:
Android
J2EE
Java
Android
Java
Android
[J2EE, Java]
Java
[J2EE]
**上面的代碼分別示范了雙端隊列,棧的用法,所以LinkedList是一個功能非常強大的集合類。
4.各種線性表的性能分析:
|
實現機制 |
隨機訪問排名 |
迭代操作排名 |
插入操作排名 |
刪除操作排名 |
數組 |
連續內存區保存元素 |
1 |
不支持 |
不支持 |
不支持 |
ArrayList/ArrayDeque |
以數組保存元素 |
2 |
2 |
2 |
2 |
Vector |
以數組保存元素 |
3 |
3 |
3 |
3 |
LinkedList |
鏈表保存元素 |
4 |
1 |
1 |
1
|
示例:
import java.util.*; /** * Description: * <br/>Copyright (C), 2005-2008, Yeeku.H.Lee * <br/>This program is protected by copyright laws. * <br/>Program Name: * <br/>Date: * @author Yeeku.H.Lee kongyeeku@163.com * @version 1.0 */ public class TestPerformance { public static void main(String[] args) { //創建一個字符串數組 String[] tst1 = new String[900000]; //動態初始化數組元素 for (int i = 0; i < 900000; i++) { tst1[i] = String.valueOf(i); } ArrayList al = new ArrayList(); //將所有數組元素加入ArrayList集合中 long start = System.currentTimeMillis(); for (int i = 0; i < 900000 ; i++) { al.add(tst1[i]); } System.out.println("ArrayList集合添加元素的時間:" + (System.currentTimeMillis() - start)); LinkedList ll = new LinkedList(); //將所有數組元素加入LinkedList集合中 start = System.currentTimeMillis(); for (int i = 0; i < 900000 ; i++) { ll.add(tst1[i]); } System.out.println("LinkedList集合添加元素的時間:" + (System.currentTimeMillis() - start)); //迭代訪問ArrayList集合的所有元素,並輸出迭代時間 start = System.currentTimeMillis(); for (Iterator it = al.iterator();it.hasNext() ; ) { it.next(); } System.out.println("迭代ArrayList集合元素的時間:" + (System.currentTimeMillis() - start)); //迭代訪問LinkedList集合的所有元素,並輸出迭代時間 start = System.currentTimeMillis(); for (Iterator it = ll.iterator();it.hasNext() ; ) { it.next(); } System.out.println("迭代LinkedList集合元素的時間:" + (System.currentTimeMillis() - start)); } }
輸出結果:
ArrayList集合添加元素的時間:446
LinkedList集合添加元素的時間:16
迭代ArrayList集合元素的時間:11
迭代LinkedList集合元素的時間:12
**可以看出LinkedList添加元素特別快,是ArrayList的幾十倍,但遍歷時不相上下。用foreach遍歷LinkedList也比ArrayList快。
java中的集合到這里基本上總結完啦。。。
下篇會總結下操作集合的工具類:Collections,用它可以方便的把集合變成線程安全的。
轉載請注明出處:http://www.cnblogs.com/jycboy/p/javalist.html