從容器類的圖中我們知道:
collection是java類庫中的一個大的子模塊洛勉,主要還是包含List和Set兩個部分。
List接口
- 基本的ArrayList竞滓,它長于隨機訪問的元素苍糠,但是在List的中間插入和移除元素時較慢
- LinkedList,它通過代價較低的在List中間進入的插入和刪除操作襟雷,提供了優(yōu)化的順序訪問。LinkedList在隨機訪問方面相對比較慢仁烹。
二者的關系基本就是數(shù)據(jù)接口中的順序存儲結(jié)構和鏈表關系
ArrayList
import java.util.ArrayList;
import java.util.List;
class MyClass{}
public class ArrayListTest{
// 聲明存放整數(shù)的列表耸弄,這里必須用包裝器類型
List<Integer> l1 = new ArrayList<Integer>();
// 聲明存放自定義類的列表
List<MyClass> l2 = new ArrayList<MyClass>();
// 也可以像這樣不給出類型參數(shù),編譯器會在向l3中加入元素的時候進行判定
List l3 = new ArrayList();
}
常用的方法
add() 將元素添加到列表中(這是最常用的方法之一卓缰,當然了添加的元素類型必須是同一類型或者說繼承自相同基類的類型
contains() 確定某個對象是否在列表中
remove() 將某一個對象的引用傳遞給remove方法计呈,即可移除列表中的一個對象
indexOf() 持有一個對象的引用砰诵,則利用該方法可以獲得其在列表中的編號
equals() 該方法是Object基類中的一個方法remove方法在刪除元素時要要用到這個方法進行匹配
subList() 該方法允許你從較大的列表中創(chuàng)出一個片段
retainAll() 該方法是一種有效的交集操作
removeAll() 移除List中的所有元素
get() 取得指定索引位置的元素
LinkedList
像ArrayList一樣LinkedList也實現(xiàn)了基本的List接口,但是在某些方面它要比ArrayList要高效一些捌显,如插入和移除操作茁彭,但是在隨機訪問方面要遜色一些。
另外LinkedList還有一個重要的作用是用來實現(xiàn)棧扶歪、隊列以及雙端隊列等數(shù)據(jù)結(jié)構中的一些基本結(jié)構
import java.util.*;
class MyClass{}
public class LinkedListTest {
// 聲明持有String類型的列表理肺,同樣這里我們可以用List來持有LinkedList的引用
List<String> ls = new LinkedList<String>();
// 聲明持有自定義類型的列表
List<MyClass> lsm = new LinkedList<MyClass>();
// 同樣我們可以用LinkedList的引用來持有它
LinkedList<String> lss = new LinkedList<String>();
// 同ArrayList一樣我們也可以并不在聲明時賦以類型參數(shù),而再賦值時再確定
List l = new LinkedList();
}
上面的聲明方式同ArrayList是基本一樣的善镰,我們可以利用List接口來持有LinkedList對象的引用妹萨,同樣也可以用LinkedList自己來持有這個引用
getFirst() 返回列表的頭(第一個元素),而不移除它炫欺。如果List為空則拋出NoSuchElementException
element() 同getFirst()
peek() 與前兩個方法的唯一區(qū)別是乎完,如果List為空則返回null
removeFirst() 移除并返回列表頭,如果List為空竣稽,同上拋出相同的異常
remove() 同removeFirst()
poll() 與前兩個方法的唯一區(qū)別是囱怕,如果List為空則返回null
addFirst() 將某個元素插入到列表頭部
addLast() 將某個元素插入到列表尾部
add() 同addLast()
removeLast 移除并返回列表的最后一個元素
說完了List,我們一定會想到數(shù)據(jù)結(jié)構中非常重要的兩種毫别,隊列和棧娃弓,在Java中這兩種數(shù)據(jù)結(jié)構我們應該怎么實現(xiàn)呢?這就要用到我們剛介紹的LinkedList
棧和隊列
“椀夯拢”
通常指后進先出(LIFO)的容器,我們肯定會發(fā)現(xiàn)Java容器類庫的結(jié)構圖中已經(jīng)包含了棧這個結(jié)構台丛,但是基于在Java1.0中設計者的失誤導致Stack在新版本的Java中是不推薦使用(這里原因不具體廢話了,反正就是不用它便是)砾肺,然而有了LinkedList挽霉,我們完全可以自己很快的寫一個,因為說到底棧無非就是操作受限的鏈表(它只允許在鏈表的一端進行讀寫操作)变汪。
import java.util.LinkedList;
public class Stack<T> {
private LinkedList<T> storage = new LinkedList<T>();
public void push(T v) {
storage.addFirst(v);
}
public T peek() {
return storage.getFirst();
}
public T pop() {
return storage.removeFirst();
}
public boolean empty() {
return storage.isEmpty();
}
public String toString() {
return storage.toString();
}
} // /:~
這里我們將LinkedList用組合的方式封裝在我們的Stack類中侠坎,切記這里不能使用繼承,因為如果我們的Stack類繼承自LinkedList裙盾,那么從外部我們就可以獲得所有LinkedList的public接口实胸,那么棧就沒意義了(其實Java1.0中的Stack的設計就犯了這個錯誤)
“隊列”
是一個典型的先進先出(FIFO)的容器,LinkedList除了實現(xiàn)了List接口還實現(xiàn)了Queue接口,這也就是為什么我們在上面介紹LinkedList時會有那么多功能重復但是名字不同的方法的原因了番官。
public class QueueDemo {
public static void printQ(Queue queue) {
while (queue.peek() != null)
System.out.print(queue.remove() + " ");
System.out.println();
}
public static void main(String[] args) {
Queue<Integer> queue = new LinkedList<Integer>();
Random rand = new Random(47);
for (int i = 0; i < 10; i++)
queue.offer(rand.nextInt(i + 10));
printQ(queue);
Queue<Character> qc = new LinkedList<Character>();
for (char c : "Brontosaurus".toCharArray())
qc.offer(c);
printQ(qc);
}
}
Set接口
Set最最重要的特征就是不保存重復元素
Set接口主要有兩種具體的實現(xiàn):HashSet和TreeSe
而在HashSet的基礎上還實現(xiàn)了一個LinkedHashSet庐完。
- HashSet:擁有最快的查詢速度,存入HashSet的元素必須定義hashCode()方法
- TreeSet:保持元素處于排序狀態(tài)徘熔,底層為樹結(jié)構门躯。使用它可以從Set中提取有序的序列。元素必須實現(xiàn)Comparable接口
- LinkedHashSet:以插入順序保持元素讶凉,用迭代器進行遍歷時會按照插入時的順序顯示染乌,但也必須定義hashCode()方法
Set具有與Collection完全一樣的接口,因此沒有任何額外的功能缀遍,不像前面有兩個不同的List慕匠。實際上Set就是Collection,只是行為不同域醇。(這是繼承與多態(tài)思想的典型應用:表現(xiàn)不同的行為。)Set是基于對象的值來確定對象的歸屬性的蓉媳。