java編程思想讀書筆記 第十一章 持有對象(下)

1.Set
Set不保存重複的元素。如果你將相同的對象的多個實例添加到Set中,那麼它就會阻止這種重複現象。Set中最常被使用的是測試歸屬性,你可以很容易地詢問某個對象是否在某個Set中。正因如此,查找就成爲了Set中最重要的操作,因此你通常都會選擇一個HashSet的實現,它專門對快速查找進行了優化。Set和Collection完全一樣的接口,因此沒有任何額外的功能,不像前面兩個不同的List。實際上Set就是Collection,只是行爲不同。而HashSet所維護的順序與TreeSet或LinkedHashSet都不同,因爲他們的實現具有不同的元素存儲方式。TreeSet將元素存儲在紅-黑樹數據結構中,而HashSet使用的是散列函數。LinkedHashList因爲查詢速度的原因也使用了散列,但是看起來它使用了鏈表來維護元素的插入順序。如果想對結果排序,一種方式就是使用TreeSet來代替HashSet。

2.Map
將對象映射到其他對象的能力是一種解決編程問題的殺手鐗。例如,考慮一個程序,它將用來檢查java的Random類的隨機性。理想狀態下,Random可以將產生的理想的數字分別,但要想測試它,則要生成大量的隨機數,並對落入各種不同範圍的數字進行計數。Map可以很容易地解決該問題。在本例中,鍵是由Random產生的數字,而值是該數字出現的次數:

public class Satatistics {
    public static void main(String[] args) {
        Random rand = new Random(47);
        Map<Integer, Integer> map = new HashMap<Integer, Integer>();
        for (int i = 0; i < 10000; i++) {
            int r = rand.nextInt(20);
            Integer freq = map.get(r);
            map.put(r, freq == null ? 1: freq + 1);
        }
        System.out.println(map);
    }
}

在main()中,自動包裝機制將隨機生成的int轉換爲HashMap可以使用Integer的引用(不能使用基本類型的容器)。如果鍵不在容器中,get()方法將返回null(這表示第一次被找到),否則,get()方法將產生與該鍵相關聯的Integer值,然後這個值被遞增(自動包裝機制再次簡化了表達式,但是確實發生了對Integer的包裝和拆包)。在Map中可以使用containsKey和containsValue來查看是否包含某個鍵或某個值。Map與數組和其他的Collection一樣,可以很容易地擴展到多維,而我們只需將其值設爲Map(這些Map的值可以是其他容器,甚至是其他Map)。因此,我們能夠很容易地將容器組合起來從而快速地生成強大的數據結構。

3.Queue
隊列是一個典型的先進先出的容器。即從容器的一端放入事物,從另一端取出,並且事物放入容器的順序與取出的順序相同。隊列常被當作一種可靠的將對象從程序的某個區域傳輸到另一個區域的途徑。
LinkedList提供了方法以支持隊列行爲,並且它實現了Queue接口,因此LinkedList可以用作Queue的一種實現。通過將LinkedList向上轉型爲Queue,下面的例子使用了在Queue接口中與Queue接口中與Queue相關的方法:

public class QueueDemo {
    public static void printQ(Queue queue){
        while(queue.peek() != null){
            System.out.print(queue.remove()+ " ");
        }
    }
    public static void main(String[] args) {
        Queue<Integer> queue = new LinkedList<Integer>();
        Random random = new Random(47);
        for (int i = 0; i < 10; i++) {
            queue.offer(random.nextInt(i + 10));
        }
        printQ(queue);
        Queue<Character> qcCharacters = new LinkedList<Character>();
        for (char c : qcCharacters) {
            qcCharacters.offer(c);
        }
        printQ(qcCharacters);
    }
}
輸出:8 1 1 1 5 14 3 1 0 1 

offer()方法使與Queue相關的方法之一,它在允許的情況下,將一個元素插入到隊尾,或者返回false。peek()和element()都將在不移除的情況下返回對頭,但是peek()方法在隊列爲空時返回null,而element()會拋出NoSuchElementException異常。poll()和remove()方法將移除並返回對頭,但是poll()在隊列爲空時返回null,而remove()會拋出NoSuchElementException異常。自動包裝機制將會自動地將nextIn()方法的int結果轉換爲queue所需的Integer對象,將char c 轉換爲qcCharacters 所需的Character對象。Queue接口窄化了對LinkedList的方法的訪問權限,以使得只有恰當的方法纔可以使用,因此,你能夠訪問的LinkedList的方法會變少。注意Queue相關的方法提供了完整而獨立的功能。即,對於Queue所繼承的Collection,在不需要使用它的任何方法的情況下,就可以擁有一個可用的Queue。

4.PriorityQueue
先進先出描述的是最典型的隊列規則。隊列規則是指在給定一組隊列的元素的情況下,確定下一個彈出隊列的元素的規則。先進先出聲明的是下一個元素應該是等待時間最長的元素。優先級隊列聲明下一個彈出元素時最需要的元素(具有最高的優先級)。當你再PriorityQueue上調用offer()方法來插入一個對象時,這個對象會在隊列中被排序。默認的排序將使用對象在隊列中的自然順序,但是你可以通過提供自己的Comparator來修改這個順序。PriorityQueue可以確保當你調用peek()、poll()和remove()方法時,獲取的元素將時隊列中優先級最高的元素。在PriorityQueue中,重複是允許的。如果你想在PriorityQueue中使用自己的類,就必須包括額外的功能以產生自然排序,或者提供自己的Comparator。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章