一個項目中如果只是使用數組操作已知個數的對象並清楚知道每個對象的生命週期,那麼這將是一個非常簡單的程序。面對現在龐大且複雜的業務邏輯,用數組持有對象是遠遠不夠的,於是Java提供了容器類庫,以達到管理可變對象個數的要求。
一、Java容器類庫
- 用途——保存對象
- Arrays.asList()方法接受一個數組或一個用逗號分割的元素列表(及接收一個可變參數),並將其轉換爲一個List對象;
- Collections.addAll()方法接受一個Collection對象,以及一個數組或是用一個逗號分割的列表(及接收一個可變參數),將元素添加到Collection中;
- Collection本身有一個構造器可以接收另一個Collection用以初始化自身;
- Collection.addAll()只能接收另一個Collection,所以用起來並沒有Collections.addAll()靈活,所以優先選用後者。
看一個例子:
import java.util.*; public class Box{ //創建一個接收Collention的方法 public static Collection setCollection(Collection con){ con.add("one"); con.add("two"); con.add("three"); con.add("three"); con.add("two"); return con; } //返回一個接收Map的方法 public static Map setMap(Map map){ map.put("one","one"); map.put("two","two"); map.put("three","three"); map.put("three","three"); return map; } public static void main(String[] args){ System.out.println(setCollection(new ArrayList<String>())); System.out.println(setCollection(new LinkedList<String>())); System.out.println(setCollection(new HashSet<String>())); System.out.println(setCollection(new TreeSet<String>())); System.out.println(setCollection(new LinkedHashSet<String>())); System.out.println(setMap(new HashMap<String,String>())); System.out.println(setMap(new TreeMap<String,String>())); System.out.println(setMap(new LinkedHashMap<String,String>())); } }
編譯執行:
分析這個例子我們得出的結論:
- ArrayList、LinkedList、HashSet、TreeSet、LinkedHashSet 都可以向上轉型爲Collection,即Collection爲這些集合的接公共口。
- Map爲HashMap(有最快的查找技術)、TreeMap、LinkedHashMap的公共接口。
- List集合包含ArrayList和LinkedList集合,這倆個集合都可以存儲重複對象。
- Set集合包含HashSet(使用了散列函數,最快的獲取元素方式)、TreeSet、LinkedHashSet ,存儲不同的對象。
- TreeSet(將元素存儲在紅-黑樹數據結構中)按照比較結果的升序保存對象。
- LinkedHashSet (同樣使用了散列,同時使用鏈表來維護元素的插入順序)按照被添加的順序保存對象。
- TreeMap按照比較結果的升序保存鍵。
- LinkedHashSet 按照被添加的順序保存鍵。
- 觀察運行結果發現有倆個注,意思就是我們使用了線程不安全(後續詳細解讀)的集合,但是並不會影響程序的運行。
二、List集合
可以將元素維護在特定的序列中(一種可變的序列)。其在Collection的基礎上添加了大量的方法,使得其可以在List的中間插入和移除元素。
具體實現了倆種List:
- ArrayList——擅長隨機訪問數據,在中間插入和移除元素較慢。
- LinkedList——中間插入和移除元素優於前者,擅長順序訪問,隨機訪問較慢
*幾個常用方法:
- contains()是接口Collection中的方法,用以判斷一個集合是否包含某個對象,返回一個boolean類型的值,所以在List的倆個實現類中都有此方法。
- remove(引用)——刪除集合中指定引用的對象。
- indexOf(引用)——獲取指定引用在集合中對應的索引值。
- subList(startIndex,endIndex)——可從大的列表中創建一個片斷(開始索引到結束索引間的片斷,包括startIndex和endIndex)。
- containAll()——一個集合中是否包含另一個集合(也可以說成片斷),集合中元素的順序不會影響判斷結果。
- retain()——求倆個集合的交集部分(判斷時內部依賴與equals)。
- removeAll()——從本集合中刪除參數集合的所有元素(依賴equals)。
- set()——可以替換指定索引下的元素。
- addAll()——List重寫Collection的方法,可以在指定索引下插入指定的片斷。當然也可以直接在集合後邊追加另一個片斷。
- clear()——清除集合中的所有元素
- isEmpty()——返回一個boolean類型值,判斷集合是否爲空。
- toArray()——可將集合轉換成一個數組,傳遞指定類型的集合,會生成指定類型的數組。
*LinkedList集合:
其中含有使其用作棧、隊列或雙端隊列的方法。
getFirst()\element()——倆個方法完全一樣,都返回列表的第一個元素,並不移除它,如果List爲空,則拋出NoSuchElement-Exception。
peek()——都返回列表的第一個元素,並不移除它,如果List爲空返回null。
removeFirst()\remove()——倆個方法相同,它們移除並返回列表的頭,而在列表爲空時拋出NoSuchElementException異常。
poll()——與上邊倆個稍有差異,只是在列表爲空時返回null。
removeLast()——移除並返回列表中最後一個元素。
addFirst()\add()\addLast()——他們都將元素插入到列表的尾(端)部。
——stack(棧):
稱爲後進先出(LIFO)的容器,也被稱爲疊加棧。LinkedList具有能夠直接實現棧的所有功能的方法,因此可以直接將LinkedList作爲棧使用。
public class Stack<T>{
private LinkedList<T> stack=new LinkedList<T>();
public void push(T t){
stack.addFirst(t);
}
public T peek(){
return stack.getFirst();
}
public T pop(){
return stack.removeFirst();
}
public boolean empty(){
return stack.isEmpty();
}
public String toString(){
return stack.toString();
}
}
雖然在Java的util類庫中創建了Stack類,但是在實際開發中更提倡使用上述使用LinkedList創建的棧,需要注意的一點是在創建Stack類時最好只調用棧需要的方法而不要將整個LinkedList(其中含有大量其他方法)繼承下來。三、Set集合
不保存重複的元素,因爲很容易詢問某個對象是否在某個Set中,所以查找是Set集合非常重要的操作,HashSet專門對快速查找進行了優化。Set與Collection有完全一樣的接口,沒有任何額外的功能,只是行爲有所不同(此爲繼承與多態思想的典型應用——表現不同行爲)。
import java.util.*;
public class Box{
public static void main(String[] args){
Set<String> t_box=new TreeSet<String>();
//向Set集合中添加數據
Collections.addAll(t_box,"B,A,C,E,D,F".split(","));
Set<String> h_box=new HashSet<String>();
Collections.addAll(h_box,"E,D,F".split(","));
System.out.println(t_box);
System.out.println(h_box);
System.out.println("contains:"+t_box.contains("A"));
System.out.println("containsAll:"+t_box.containsAll(h_box));
h_box.removeAll(t_box);
System.out.println(h_box);
System.out.println(t_box);
System.out.println("isEmpty:"+h_box.isEmpty());
}
}
運行結果:
使用contains()和containsAll()方法來測試Set的歸屬性。
未完待續。。。。。。