1. 程式人生 > >Thinking in Java讀書筆記(三) (更新中。。。)

Thinking in Java讀書筆記(三) (更新中。。。)

第十一章 持有物件

  1. Java容器類庫 Java容器類庫的用途是“儲存物件”,這裡劃分兩個概念: (1)Collection   一個獨立元素的序列,這些元素都服從一條或多條規則。List必須按照插入的順序儲存元素,而set不能有重複的元素。Queue按照排隊規則來確定物件產生的順序(通常與它們被插入的順序相同)。 (2)Map   一組成對的“鍵值對”物件,允許你使用鍵來查詢值。 在這裡插入圖片描述 注:淡綠色表示介面,紅色表示常用類。

  2. 泛型和型別安全容器 使用泛型可以在編譯器防止將錯誤型別的物件放置到容器中。 使用方法是在容器後用尖括號括起型別引數(可以有多個),它指定了這個容器例項可以儲存的型別,如ArrayList<Type>。並且這個型別可以向上轉型。

  3. Collection新增一組元素: (1) Arrays.asList():接受一個數組或是一個用逗號分隔的元素列表(使用可變引數),並將其轉換為一個List物件。 (2) Collections.addAll():接受一個Collection物件,以及一個數組或是一個用逗號分割的列表,將元素新增到Collection中。 (3) Collection.addAll():將一個Collection物件全部新增進去。只能接受Collection物件作為引數,不如前兩種使用可變引數列表的靈活。

    import java.util.*;
    
    public class AddingGroups {
    	public
    static void main(String[] args) { Collection<Integer> collection = new ArrayList<Integer>(Arrays.asList(1, 2, 3, 4, 5)); Integer[] moreInts = {6, 7, 8, 9, 10}; collection.addAll(Arrays.asList(moreInts)); //Run significantly faster, but you can't construct a Collection this way: Collections.
    addAll(collection, 11, 12, 13, 14, 15); Collections.addAll(collection, moreInts); //Produces a list "backed by" an array: List<Integer> list = Arrays.asList(16, 17, 18, 19, 20); list.set(1, 99); //OK -- modify an element //list.add(21); //Running error because the underlying array cannot be resized. } }

    Collection構造器可以接受另一個Collection,用它來將自身初始化,因此你可以使用Arrays.List()來為這個構造器產生輸入。但是,Collection.addAll()方法執行起來要快得多,而且構建一個不包含元素的Collection,然後呼叫Collections.addAll()這種方式很方便,所以這才是首選辦法。

  4. 容器的列印 陣列需要藉助Arrays.toString()來打印表示,但列印容器無需任何幫助:

    import java.util.*;
    
    public class PrintingContainers {
    	static Collection fill(Collection<String> collection) {
    		collection.add("rat");
    		collection.add("cat");
    		collection.add("dog");
    		collection.add("dog");
    		return collection;
    	}
    	static Map fill(Map<String,String> map) {
    		map.put("rat", "Fuzzy");
    		map.put("cat", "Rags");
    		map.put("dog", "Bosco");
    		map.put("dog", "Spot");
    		return map;
    	}
    	public static void main(String[] args) {
    		System.out.println(fill(new ArrayList<String>()));
    		System.out.println(fill(new LinkedList<String>()));
    		System.out.println(fill(new HashSet<String>()));
    		System.out.println(fill(new TreeSet<String>()));
    		System.out.println(fill(new LinkedHashSet<String>()));
    		System.out.println(fill(new HashMap<String,String>()));
    		System.out.println(fill(new TreeMap<String,String>()));
    		System.out.println(fill(new LinkedHashMap<String,String>()));
    	}
    }
    /*Output:
    [rat, cat, dog, dog]
    [rat, cat, dog, dog]
    [rat, cat, dog]
    [cat, dog, rat]
    [rat, cat, dog]
    {rat=Fuzzy, cat=Rags, dog=Spot}
    {cat=Rags, dog=Spot, rat=Fuzzy}
    {rat=Fuzzy, cat=Rags, dog=Spot}
    */
    

    這裡可以看出Collection和Map的區別在於每個“槽”儲存的元素個數。Collection每個槽只能儲存一個元素。而Map在每個槽內儲存了兩個物件,即鍵和與之相關聯的值。Collection打印出來的內容用方括號括住,每個元素由逗號分隔。Map則用大括號括住,鍵與值由等號聯絡(鍵在等號左邊,值在右邊)。 另外,該例子可以看出一些容器的特性:

    型別 特性
    ArrayList, LinkedList 插入順序和輸出順序一致,可以重複
    HashSet, TreeSet 插入順序和輸出順序不一致,不重複
    LinkedHashSet 插入順序和輸出順序一致,不重複
    HashMap, TreeMap, LinkedHashMap 鍵值對儲存,鍵不重複
  5. List List承諾可以將元素維護在特定的序列中。List介面在Collection的基礎上加入了大量的方法,使得可以在List中間可以插入和移除元素。有兩種型別的List: (1) 基本的ArrayList,它長於隨機訪問元素,但是在List的中間插入和移除元素時比較慢。 (2) LinkedList,它通過代價較低的在List中間進行得插入和刪除操作,提供了優化的順序訪問。LinkedList在隨機訪問方面相對比較慢,但是它的特性集較ArrayList更大。 與陣列不同,List允許在它被建立之後新增元素、移除元素、或者自我調整尺寸,即一個可修改的序列。

    方法 功能
    contains(Object obj) 確定某個物件是否在列表中
    remove(int index) , remove(Object obj) 移除一個物件(刪除沒有的物件返回false)
    indexOf(Object obj) 返回該物件在List中所處位置的索引編號(找不到就返回-1)
    retainAll(Collection c) 返回交集
    removeAll(Collection c) 從列表中移除指定collection中包含的其所有元素
    set(int index, E element) 設定下標為index的元素為element
    subList(int from_index, int to_index) 擷取下標從from_index到to_index的列表
    addALL(int index, Collection c) 在下標index處插入指定collection
    toArray() 轉變為具有合適尺寸的陣列
    add(int index, E element) 在下標index處新增element
    get(int index) 獲取下標為index的值
  6. 迭代器 迭代器是一個物件,它的工作是遍歷並選擇物件中的物件。 Java的Iterator只能單向移動,這個Iterator只能用來: (1) 使用方法iterator()要求容器返回一個Iterator。Iterator將準備好返回序列的第一個元素。 (2) 使用next()獲得序列中的下一個元素。 (3) 使用hasNext()檢查序列中是否還有元素。 (4) 使用remove()將迭代器新近返回的元素刪除。 迭代器統一了對容器的訪問方式。

    ListIterator 更加強大的Iterator子型別,只能用於各種List類的訪問。ListIterator可以雙向移動。 (1) 使用方法listIterator()要求容器返回一個指向List開始處的ListIterator。使用方法listIterator(n)要求容器返回一個一開始指向List索引為n的元素處的ListIterator。 (2) 使用next()獲得序列中的下一個元素。使用previous()獲得序列中的上一個元素。 (3) 使用hasNext()檢查序列中是否還有元素。使用hasPrevious()檢查序列是否有上一個元素。 (4) 使用remove()將迭代器新近返回的元素刪除。 (5) 使用set()修改迭代器新近返回的元素。

  7. LinkedList LinkedList也實現List介面,插入和刪除操作比較高效,但在隨機訪問操作方面遜色一籌。LinkedList還添加了可以使其使用棧、佇列或雙端佇列的語法。

    方法 功能
    getFirst(), element() 返回列表的第一個元素,而並不移除它,如果List為空,丟擲NoSuchElementException
    peek() 功能同上,列表為空時返回null
    removeFirst(), remove() 移除並返回列表的第一個元素,列表為空時返回NoSuchElementException
    poll() 功能同上,列表為空時返回null
    add(), addFirst(), addLast() 將某個元素插入到列表的尾端
    removeLast() 移除並返回列表的最後一個元素
  8. Set Set不儲存重複的元素。查詢是Set中最重要的操作,其中HashSet對快速查詢進行了優化。最常見操作之一就是使用contains()測試Set的歸屬性。

  9. Map 將物件對映到其他物件。與陣列和其他Collection一樣,Map很容易可以擴充套件到多維,而我們只需要將其值設定為Map(這些Map的值可以是其他容器,甚至是其他Map),例如:Map<Person, List< Pet >>。

  10. Queue 佇列是一個典型的先進先出(FIFO)容器。 佇列常被當做一種可靠的將物件從程式的某各區域傳輸到另一個區域的途徑。LinkedList提供了方法以支援佇列的行為,並實現了Queue介面。可以將LinkedList向上轉型為Queue以使用Queue的方法。offer()方法是與Queue相關的方法之一,它在允許的情況下,將一個元素插入到隊尾,或者返回false。

    PriorityQueue 優先順序佇列宣告下一個彈出元素時最重要的元素(具有最高的優先順序)。

  11. Foreach與迭代器 foreach利用Itretrable介面在序列中移動,該介面包含一個能夠產生Iterator的iterator()方法。所以建立任何實現Iterable的類都可以將它作用於foreach語句:

    import java.util.*;
    
    public class IterableClass implements Iterable<String> {
    
    	protected String[] words = ("And that is how " + "we know the Earth to be banana-shaped.").split(" ");
    
    	public Iterator<String> iterator() {
    		return new Iterator<String>() {
    			private int index = 0;
    			public boolean hasNext() { return index < words.length; }
    			public String next() { return words[ index++]; }
    			public void remove() { throw new UnsupportedOperationException(); }
    		};
    	}
    	
    	public static void main(String[] args) {
    		for(String s : new IterableClass())
    			System.out.println(s + " ");
    	}
    }
    /*Output:
    And 
    that 
    is 
    how 
    we 
    know 
    the 
    Earth 
    to 
    be 
    banana-shaped. 
    */