1. 程式人生 > >04-java.util.Collections+Collections.sort()方法的練習

04-java.util.Collections+Collections.sort()方法的練習

1、java.util.Collections:集合框架的工具類,裡面的方法都是靜態方法。此類完全由在collection上進行操作或返回collection的靜態方法組成。如果為此類的方法所提供的collection或類物件為null,則這些方法都將丟擲NullPointerException

2、方法

(1)static <T> boolean addAll(Collection<? super T> c, T... elements):將所有指定元素新增到指定collection中。可以分別指定要新增的元素,或者將它們指定為一個數組。此便捷方法的行為與c.addAll(Arrays.asList(elements))的行為是相同的,但在大多數實現下,此方法執行起來可能要快得多。在分別指定元素時,此方法提供了將少數元素新增到現有collection中的一個便捷方式:

         Collections.addAll(flavors, "Peaches 'n Plutonium", "Rocky Racoon");

(2)static <T> Queue<T> asLifoQueue(Deque<T> deque):以後進先出(Lifo)Queue的形式返回某個Deque的檢視。方法add()被對映到push(),remove()被對映到pop()等等。在希望使用某一方法獲取一個Queue並且需要它具有Lifo順序時,此方法很有用。每次在此方法返回的佇列上呼叫方法都將導致在底層實現佇列上呼叫該方法一次,並伴隨一個異常。addAll()方法是作為底層實現佇列上的addFirst()呼叫序列實現的

(3)static <T> int binarySearch(List<? extends Comparable<? super T>> list, T key):使用二分搜尋法搜尋指定列表,以獲得指定物件。在進行此呼叫之前,必須根據列表元素的自然順序對列表進行升序排序(通過sort(List)方法)。如果沒有對列表進行排序,則結果是不確定的。如果列表包含多個等於指定物件的元素,則無法保證找到的是哪一個

注:沒有順序,不能折半查詢

(4)static <T> int binarySearch(List<? extends T> list, T key, Comparator<? super T> c):使用二分搜尋法搜尋指定列表,以獲得指定物件。在進行此呼叫之前,必須根據指定的比較器對列表進行升序排序(通過sort(List, Comparator)方法)。如果沒有對列表進行排序,則結果是不確定的。如果列表包含多個等於指定物件的元素,則無法保證找到的是哪一個

注:沒有順序,不能折半查詢

(5)static <E> Collection<E> checkedCollection(Collection<E> c, Class<E> type):返回指定collection的一個動態型別安全檢視。試圖插入一個錯誤型別的元素將導致立即丟擲ClassCastException。假設在生成動態型別安全檢視之前,collection不包含任何型別不正確的元素,並且所有對該collection的後續訪問都通過該檢視進行,則可以保證該collection不包含型別不正確的元素

/**
 * 一般的程式語言機制中都提供了編譯時(靜態)型別檢查,但是一些未經檢查的強制轉換可能會使此機制無效。
 * 通常這不是一個問題,因為編譯器會在所有這類未經檢查的操作上發出警告。但有的時候,只進行單獨的靜態型別檢查並不夠。
 * 例如,假設將 collection 傳遞給一個第三方庫,則庫程式碼不能通過插入一個錯誤型別的元素來毀壞 collection。
 *
 *
 * 動態型別安全檢視的另一個用途是除錯。
 * 假設某個程式執行失敗並丟擲 ClassCastException,這指示一個型別不正確的元素被放入已引數化 collection 中。
 * 不幸的是,該異常可以發生在插入錯誤元素之後的任何時間,因此,這通常只能提供很少或無法提供任何關於問題真正來源的資訊。
 * 如果問題是可再現的,那麼可以暫時修改程式,使用一個動態型別安全檢視來包裝該 collection,通過這種方式可快速確定問題的來源。例如,以下宣告:
 *
 * Collection<String> c = new HashSet<String>();
 *
 * 可以暫時用下面的宣告代替:
 *
 * Collection<String> c = Collections.checkedCollection(new HashSet<String>(), String.class);
 *
 * 再次執行程式會造成它在將型別不正確的元素插入 collection 的地方失敗,從而清楚地識別問題的來源。
 * 問題得以解決後,可以將修改後的宣告轉換回原來的宣告。
 *
 * 返回的 collection 不會 將 hashCode 和 equals 操作傳遞給底層實現 collection,但這依賴於 Object 的 equals 和 hashCode 方法。
 * 在底層實現 collection 是一個 set 或一個列表的情況下,有必要遵守這些操作的協定。
 *
 * 如果指定 collection 是可序列化的,則返回的 collection 也將是可序列化的。
 */

(6)static <E> List<E> checkedList(List<E> list, Class<E> type):返回指定列表的一個動態型別安全檢視。試圖插入一個錯誤型別的元素將導致立即丟擲ClassCastException。假設在生成動態型別安全檢視之前,列表不包含任何型別不正確的元素,並且所有對該列表的後續訪問都通過該檢視進行,則可以保證此列表不包含型別不正確的元素

注:如果指定列表是可序列化的,則返回的列表也將是可序列化的

(7)static <K, V> Map<K, V> checkedMap(Map<K, V> m, Class<K> keyType, Class<V> valueType):返回指定對映的一個動態型別安全檢視。試圖插入一個具有錯誤型別鍵或值的對映關係將導致立即丟擲ClassCastException。類似地,試圖修改當前與鍵關聯的值(無論是直接通過對映自身,還是通過一個從該對映項集檢視中獲得的Map.Entry例項)都將導致立即丟擲ClassCastException。假設在生成動態型別安全檢視之前,對映中不包含任何型別不正確的鍵或值,並且所有對對映的後續訪問都通過該檢視(或其collection檢視之一)進行,則可以保證該對映不包含型別不正確的鍵或值

注:如果指定對映是可序列化的,則返回的對映也將是可序列化的

(8)static <E> Set<E> checkedSet(Set<E> s, Class<E> type):返回指定set的一個動態型別安全檢視。試圖插入一個錯誤型別的元素將導致立即丟擲ClassCastException。假設在生成動態型別安全檢視之前,set不包含任何型別不正確的元素,並且所有對該set的後續訪問都通過該檢視進行,則可以保證該set不包含型別不正確的元素

注:如果指定set是可序列化的,則返回的set也將是可序列化的

(9)static <K, V> SortedMap<K, V> checkedSortedMap(SortedMap<K, V> m, Class<K> keyType, Class<V> valueType):返回指定有序對映的一個動態型別安全檢視。試圖插入一個具有錯誤型別鍵或值的對映關係將導致立即丟擲ClassCastException。類似地,試圖修改當前與鍵關聯的值(無論是直接通過對映自身,還是通過一個從該對映項集檢視中獲得的Map.Entry例項)將導致立即丟擲ClassCastException。假設在生成動態型別安全檢視之前,對映中不包含任何型別不正確的鍵或值,並且所有對對映的後續訪問都通過該檢視(或其collection檢視之一)進行,則可以保證此對映不包含型別不正確的鍵或值

注:如果指定對映是可序列化的,則返回的對映也將是可序列化的

(10)static <E> SortedSet<E> checkedSortedSet(SortedSet<E> s, Class<E> type):返回指定有序set的一個動態型別安全檢視。試圖插入一個錯誤型別的元素將導致立即丟擲ClassCastException。假設在生成動態型別安全檢視之前,有序set不包含任何型別不正確的元素,並且所有對該有序set的後續訪問都通過該檢視進行,則可以保證該有序set不包含型別不正確的元素

注:如果指定的有序set是可序列化的,則返回的有序set也將是可序列化的

(11)static <T> void copy(List<? super T> dest, List<? extends T> src):將所有元素從一個列表複製到另一個列表。執行此操作後,目標列表中每個已複製元素的索引將等同於源列表中該元素的索引。目標列表的長度至少必須等於源列表。如果目標列表更長一些,也不會影響目標列表中的其餘元素

(12)static boolean disjoint(Collection<?> c1, Collection<?> c2):如果兩個指定collection中沒有相同的元素,則返回true

(13)static final <T> List<T> emptyList():返回空的列表(不可變的)。此列表是可序列化的。實現此方法不需要為每次呼叫建立一個單獨的List物件。使用此方法的開銷與使用like-named欄位相當(與此方法不同,該欄位不提供型別安全)

        List<String> s = Collections.emptyList();

(14)static final <K, V> Map<K, V> emptyMap():返回空的對映(不可變的)。此對映是可序列化的。實現此方法不需要為每次呼叫建立一個單獨的Map物件。使用此方法的開銷與使用like-named欄位相當(與此方法不同,該欄位不提供型別安全)

        Map<String, Date> s = Collections.emptyMap();

(15)static final <T> Set<T> emptySet():返回空的set(不可變的)。此set是可序列化的。實現此方法不需要為每次呼叫建立一個單獨的Set物件。使用此方法的開銷與使用like-named欄位相當(與此方法不同,該欄位不提供型別安全)

        Set<String> s = Collections.emptySet();

(16)static <T> Enumeration<T> enumeration(Collection<T> c):返回一個指定collection上的列舉。此方法提供與遺留API的互操作性,遺留API需要一個列舉作為輸入

(17)static <T> void fill(List<? super T> list, T obj):使用指定元素替換指定列表中的所有元素(可以將集合重新初始化一次)

(18)static int frequency(Collection<?> c, Object o):返回指定collection中等於指定物件的元素數

(19)static int indexOfSubList(List<?> source, List<?> target):返回指定源列表中第一次出現指定目標列表的起始位置。如果沒有出現這樣的列表,則返回-1

(20)static int lastIndexOfSubList(List<?> source, List<?> target):返回指定源列表中最後一次出現指定目標列表的起始位置。如果沒有出現這樣的列表,則返回-1

(21)static <T> ArrayList<T> list(Enumeration<T> e):返回一個數組列表,它按返回順序包含指定列舉返回的元素。此方法提供返回列舉的遺留API與需要collection的新API之間的互操作性

注:

列舉-->集合(ArrayList):static <T> ArrayList<T> list(Enumeration<T> e)

集合-->列舉:static <T> Enumeration<T> enumeration(Collection<T> c)    (老的程式碼只認識列舉,就要列舉,此時就需要將集合轉成列舉)

(22)static <T extends Object & Comparable<? super T>> T max(Collection<? extends T> coll):根據元素的自然順序,返回給定collection的最大元素。collection中的所有元素都必須實現Comparable介面。此外,collection中的所有元素都必須是可相互比較的(也就是說,對於collection中的任意e1和e2元素,e1.compareTo(e2);不得丟擲ClassCastException)

(23)static <T> T max(Collection<? extends T> coll, Comparator<? super T> comp):根據指定比較器產生的順序,返回給定collection的最大元素。collection中的所有元素都必須可通過指定比較器相互比較(也就是說,對於collection中的任意e1和e2元素,comp.compare(e1, e2);不得丟擲ClassCastException)

(24)static <T extends Object & Comparable<? super T>> T min(Collection<? extends T> coll):根據元素的自然順序返回給定collection的最小元素。collection中的所有元素都必須實現Comparable介面。此外,collection中的所有元素都必須是可相互比較的(也就是說,對於collection中的任意e1和e2元素,e1.compareTo(e2);不得丟擲ClassCastException)

(25)static <T> T min(Collection<? extends T> coll, Comparator<? super T> comp):根據指定比較器產生的順序,返回給定collection的最小元素。collection中的所有元素都必須可通過指定比較器相互比較(也就是說,對於collection中的任意e1和e2元素,comp.compare(e1, e2);不得丟擲ClassCastException)

(26)static <T> List<T> nCopies(int n, T o):返回由指定物件的n個副本組成的不可變列表。新分配的資料物件非常小(它只包含一個對該資料物件的引用)。在通過與List.addAll()方法組合來增大列表時,此方法很有用。返回的列表是可序列化的

(27)static <E> Set<E> newSetFromMap(Map<E, Boolean> map):返回指定對映支援的set。得到的set與底層實現對映有相同的順序、併發性和效能特徵。事實上,此工廠方法提供了一個對應於任何Map實現的Set實現。不必在已經有一個對應Set實現(比如HashMap或TreeMap)的Map實現上使用此方法。每次在此方法返回的set上呼叫方法都將導致在底層實現對映或其keySet檢視上呼叫該方法一次,並伴隨一個異常。addAll()方法是作為底層實現對映上的put呼叫序列實現的。在呼叫此方法時,指定對映必須為空,並且不能在此方法返回之後直接訪問。如果將對映建立為空,直接傳遞給此方法,並且沒有保留對該對映的引用,則這些條件都可以得到保證,如以下程式碼片段所示:

        Set<Object> weakHashSet = Collections.newSetFromMap(new WeakHashMap<Object, Boolean>());

(28)static <T> boolean replaceAll(List<T> list, T oldVal, T newVal):使用另一個值替換列表中出現的所有某一指定值

注:等價於 set(index, element);

        List<String> list = new ArrayList<String>();
        list.add("abc");
        list.add("aa");
        list.add("zzz");
        System.out.println(list);   //[abc, aa, zzz]
        Collections.replaceAll(list, "abc", "nba"); //等效於:(1)index = indexOf("xxx") + (2)set(index, element)。 即 set(indexOf("abc"), "nba")
        System.out.println(list);   //[nba, aa, zzz]

(29)static void reverse(List<?> list):反轉指定列表中元素的順序(對List集合進行反轉)

(30)static <T> Comparator<T> reverseOrder():返回一個比較器,它強行逆轉實現了Comparable介面的物件collection的自然順序(自然順序是通過物件自身的compareTo()方法強行排序的)。此方法允許使用單個語句,以逆自然順序對實現了Comparable介面的物件collection(或陣列)進行排序(或維護)。返回的比較器是可序列化的

        //假設a是一個字串陣列。那麼下面程式碼將 按照逆字典(字母)順序對陣列進行排序
        Arrays.sort(a, Collections.reverseOrder());
        TreeSet<String> ts = new TreeSet<String>();
        ts.add("abc");
        ts.add("zzz");
        ts.add("aa");
        System.out.println(ts); //[aa, abc, zzz]

        /**
         * 按字母順序的倒序排列
         * Collections.reverseOrder():返回一個比較器,該比較器強行逆轉實現了Comparable介面的物件collection的自然順序
         */
        TreeSet<String> ts2 = new TreeSet<String>(Collections.reverseOrder());
        ts2.add("abc");
        ts2.add("zzz");
        ts2.add("aa");
        System.out.println(ts2); //[zzz, abc, aa]

        /**
         * TreeSet<String> ts2 = new TreeSet<String>(Collections.reverseOrder()); 的實現程式碼
         * 使用匿名內部類
         * new Comparator是因為String本身已經實現Comparable,且不能被覆蓋
         */
        TreeSet<String> ts3 = new TreeSet<String>(new Comparator<String>() {
            @Override
            public int compare(String o1, String o2) {
                //將o1.compareTo(o2)中的o1與o2交換位置,即可完成字母順序的倒序
                return o2.compareTo(o1);
            }
        });

(31)static <T> Comparator<T> reverseOrder(Comparator<T> cmp):返回一個比較器,它強行逆轉指定比較器的順序。如果指定比較器為null,則此方法等同於reverseOrder()(換句話說,它返回一個比較器,該比較器將強行逆轉實現了Comparable介面的物件collection的自然順序)。返回的比較器是可序列化的(假設指定的比較器也是可序列化的或者為null)

        //若本身是帶比較器 new ComparatorByLength
        TreeSet<String> ts = new TreeSet<String>(new ComparatorByLength());
        ts.add("abc");
        ts.add("zzz");
        ts.add("aa");
        System.out.println(ts); //[aa, abc, zzz]

        /**
         * 按長度從大到小的順序排列(逆序)
         * Collections.reverseOrder(Comparator):返回一個比較器,該比較器強行逆轉指定比較器的順序
         */
        TreeSet<String> ts2 = new TreeSet<String>(Collections.reverseOrder(new ComparatorByLength()));
        ts2.add("abc");
        ts2.add("zzz");
        ts2.add("aa");
        System.out.println(ts2); //[zzz, abc, aa]

注:凡是涉及到物件排序的,想逆序都用reverseOrder(),不是隻有TreeSet能使用此方法

        Collections.sort(list, new ComparatorByLength());
        Collections.sort(list, Collections.reverseOrder(new ComparatorByLength()));

(32)static void rotate(List<?> list, int distance):根據指定的距離輪換指定列表中的元素。呼叫此方法後,對於0和list.size()-1(包括)之間的所有 i 值,索引 i 處的元素將是以前位於索引(i - distance) mod list.size()處的元素(此方法對列表的大小沒有任何影響)

(33)static void shuffle(List<?> list):使用預設隨機源對指定列表進行置換。所有置換髮生的可能性都是大致相等的。如果指定列表沒有實現RandomAccess介面並且是一個大型列表,則此實現在改組列表前將指定列表轉儲到陣列中,並將改組後的陣列轉儲回列表中。這避免了二次行為,該行為是原地改組一個“有序訪問”列表引起的

應用舉例:撲克牌洗牌、骰子等。撲克牌可以看做是一個物件,包含花色、數字等屬性。將new的撲克牌物件存入集合,可對集合中的所有撲克牌物件進行洗牌操作,即打亂順序

        List<String> list = new ArrayList<String>();
        list.add("abc");
        list.add("aa");
        list.add("zzz");
        System.out.println(list);   //[abc, aa, zzz]
        Collections.shuffle(list);
        System.out.println(list);   //將集合中的元素打亂順序(隨機)

(34)static void shuffle(List<?> list, Random rnd):使用指定的隨機源對指定列表進行置換。所有置換髮生的可能性都是相等的,假定隨機源是公平的。如果指定列表沒有實現RandomAccess介面並且是一個大型列表,則此實現在改組列表前將指定列表轉儲到一個數組中,並將改組後的陣列轉儲回列表中。這避免了二次行為,該行為是原地改組一個“有序訪問”列表引起的

(35)static <T> Set<T> singleton(T o):返回一個只包含指定物件的不可變set。返回的set是可序列化的

(36)static <T> List<T> singletonList(T o):返回一個只包含指定物件的不可變列表。返回的列表是可序列化的

(37)static <K, V> Map<K, V> singletonMap(K key, V value):返回一個不可變的對映,它只將指定鍵對映到指定值。返回的對映是可序列化的

(38)static <T extends Comparable<? super T>> void sort(List<T> list):根據元素的自然順序對指定列表按升序進行排序。列表中的所有元素都必須實現Comparable介面。此外,列表中的所有元素都必須是可相互比較的(也就是說,對於列表中的任何e1和e2元素,e1.compareTo(e2);不得丟擲ClassCastException)。此排序方法具有穩定性:不會因呼叫sort()方法而對相等的元素進行重新排序。指定列表必須是可修改的,但不必是大小可調整的。此實現將指定列表轉儲到一個數組中,並對陣列進行排序,在重置陣列中相應位置處每個元素的列表上進行迭代

注:最下面有練習

    /**
     * sort(List)方法的實現原理(自然順序排序)
     * 1、集合的型別不明確,用泛型?表示
     * 2、泛型要具備比較性才能排序,需要做限制,必須是Comparable的子類,即 <T extends Comparable>
     * 3、Comparable後面也有泛型,可以是T或T的父類,即 Comparable<? super T>
     *
     * @param list
     * @param <T>
     */
    public static <T extends Comparable<? super T>> void mySort(List<T> list) {
        //list.size()-1:最後一個元素不用比
        for (int i = 0; i < list.size() - 1; i++) {
            for (int j = i + 1; j < list.size(); j++) {
//                if (list.get(i) > list.get(j)) {
                //因為<T extends Comparable>,可以使用compareTo()方法比較大小
                if (list.get(i).compareTo(list.get(j)) > 0) {
                    //交換順序
                    /*T temp = list.get(i);
                    list.set(j, temp);
                    list.set(i, list.get(j));*/
                    Collections.swap(list, i, j);
                }
            }
        }
    }

(39)static <T> void sort(List<T> list, Comparator<? super T> c):根據指定比較器產生的順序對指定列表進行排序。此列表內的所有元素都必須可使用指定比較器相互比較(也就是說,對於列表中的任意e1和e2元素,c.compare(e1, e2);不得丟擲ClassCastException)。此排序被保證是穩定的:不會因呼叫sort()而對相等的元素進行重新排序。此實現將指定列表轉儲到一個數組中,並對陣列進行排序,在重置陣列中相應位置每個元素的列表上進行迭代

注:如果引數List<T>中的T也實現了Comparator,在sort()方法中,最終還是以引數Comparator<? super T>的比較器為主。另外,可以使用父類的比較器,但不能使用子類的比較器,所以引數中的比較器後的泛型用<? super T>

    /**
     * sort(List, Comparator)方法的實現原理(比較器排序)
     * 1、Comparator後面也有泛型,可以是T或T的父類,即 Comparator<? super T>
     * 
     * @param list
     * @param c
     * @param <T>
     */
    public static <T> void mySort(List<T> list, Comparator<? super T> c) {
        for (int i = 0; i < list.size() - 1; i++) {
            for (int j = i + 1; j < list.size(); j++) {
                //因為引數傳入了Comparator比較器,可以使用Comparator的compare()方法比較大小
                if (c.compare(list.get(i), list.get(j)) > 0) {
                    Collections.swap(list, i, j);
                }
            }
        }
    }

(40)static void swap(List<?> list, int i, int j):在指定列表的指定位置處交換元素(如果指定位置相同,則呼叫此方法不會更改列表)

(41)static <T> Collection<T> synchronizedCollection(Collection<T> c):返回指定collection支援的同步(執行緒安全的)collection。為了保證按順序訪問,必須通過返回的collection完成所有對底層實現collection的訪問。在返回的collection上進行迭代時,使用者必須手工在返回的collection上進行同步:

        Collection c = Collections.synchronizedCollection(myCollection);
        //......此處省略部分程式碼
        synchronized (c) {
            Iterator i = c.iterator(); // Must be in the synchronized block
            while (i.hasNext())
                foo(i.next());
        }

不遵從此建議將導致無法確定的行為。返回的collection不會將hashCode()和equals()操作傳遞給底層實現collection,但這依賴於Object的equals()和hashCode()方法。在底層實現collection是一個set或一個列表的情況下,有必要遵守這些操作的協定。如果指定collection是可序列化的,則返回的collection也將是可序列化的

List list = new ArrayList();    //非同步的
list = MyCollections.synList(list); //返回一個同步的list。等價於Collections.synchronizedList(list);

/**
 * Collections.synchronizedList(list)方法的實現原理
 */
class MyCollections {

    /**
     * 對外提供一個方法,將非同步的集合變成同步的集合
     * @param list
     * @return
     */
    public static List synList(List list) {
        return new MyList(list);
    }

    /**
     * 內部類:給非同步的集合加鎖
     * 一個執行緒在新增元素時,另外一個執行緒不能刪除
     */
    private class MyList implements List {

        private List list;

        //鎖
        private static final Object lock = new Object();

        MyList(List list) {
            this.list = list;
        }

        public boolean add(Object obj) {
            synchronized (lock) {
                return list.add(obj);
            }
        }

        public boolean remove(Object obj) {
            synchronized (lock) {
                return list.remove(obj);
            }
        }
    }

}

(42)static <T> List<T> synchronizedList(List<T> list):返回指定列表支援的同步(執行緒安全的)列表。為了保證按順序訪問,必須通過返回的列表完成所有對底層實現列表的訪問。在返回的列表上進行迭代時,使用者必須手工在返回的列表上進行同步:

        List list = Collections.synchronizedList(new ArrayList());
        //......此處省略部分程式碼
        synchronized (list) {
            Iterator i = list.iterator(); // Must be in synchronized block
            while (i.hasNext())
                foo(i.next());
        }

不遵從此建議將導致無法確定的行為。如果指定列表是可序列化的,則返回的列表也將是可序列化的

(43)static <K, V> Map<K, V> synchronizedMap(Map<K, V> m):返回由指定對映支援的同步(執行緒安全的)對映。為了保證按順序訪問,必須通過返回的對映完成所有對底層實現對映的訪問。在返回對映的任意collection檢視上進行迭代時,使用者必須手工在返回的對映上進行同步:

        Map m = Collections.synchronizedMap(new HashMap());
        //......此處省略部分程式碼
        Set s = m.keySet();  // Needn't be in synchronized block
        //......此處省略部分程式碼
        synchronized (m) {  // Synchronizing on m, not s!
            Iterator i = s.iterator(); // Must be in synchronized block
            while (i.hasNext())
                foo(i.next());
        }

不遵從此建議將導致無法確定的行為。如果指定對映是可序列化的,則返回的對映也將是可序列化的

(44)static <T> Set<T> synchronizedSet(Set<T> s):返回指定set支援的同步(執行緒安全的)set。為了保證按順序訪問,必須通過返回的set完成對所有底層實現set的訪問。在返回的set上進行迭代時,使用者必須手工在返回的set上進行同步:

        Set s = Collections.synchronizedSet(new HashSet());
        //......此處省略部分程式碼
        synchronized (s) {
            Iterator i = s.iterator(); // Must be in the synchronized block
            while (i.hasNext())
                foo(i.next());
        }

不遵從此建議將導致無法確定的行為。如果指定set是可序列化的,則返回的set也將是可序列化的

(45)static <K, V> SortedMap<K, V> synchronizedSortedMap(SortedMap<K, V> m):返回指定有序對映支援的同步(執行緒安全的)有序對映。為了保證按順序訪問,必須通過返回的有序對映(或其檢視)完成對所有底層有序對映的訪問。當在返回的有序對映的collection檢視或者其任何subMap、headMap或tailMap檢視進行迭代時,使用者必須手工在該對映上進行同步:

        SortedMap m = Collections.synchronizedSortedMap(new TreeMap());
        //......此處省略部分程式碼
        Set s = m.keySet();  // Needn't be in synchronized block
        //......此處省略部分程式碼
        synchronized (m) {  // Synchronizing on m, not s!
            Iterator i = s.iterator(); // Must be in synchronized block
            while (i.hasNext())
                foo(i.next());
        }

        //或者

        SortedMap m = Collections.synchronizedSortedMap(new TreeMap());
        SortedMap m2 = m.subMap(foo, bar);
        //......此處省略部分程式碼
        Set s2 = m2.keySet();  // Needn't be in synchronized block
        //......此處省略部分程式碼
        synchronized (m) {  // Synchronizing on m, not m2 or s2!
            Iterator i = s.iterator(); // Must be in synchronized block
            while (i.hasNext())
                foo(i.next());
        }

不遵從此建議將導致無法確定的行為。如果指定的有序對映是可序列化的,則返回的有序對映也將是可序列化的

(46)static <T> SortedSet<T> synchronizedSortedSet(SortedSet<T> s):返回指定有序set支援的同步(執行緒安全的)有序set。為了保證按順序訪問,必須通過返回的有序set(或其檢視)完成對所有底層實現有序set的訪問。在返回的有序set上或者其任意subSet、headSet或tailSet檢視上進行迭代時,使用者必須手工在返回的有序set上進行同步:

        SortedSet s = Collections.synchronizedSortedSet(new TreeSet());
        //......此處省略部分程式碼
        synchronized (s) {
            Iterator i = s.iterator(); // Must be in the synchronized block
            while (i.hasNext())
                foo(i.next());
        }

        //或者

        SortedSet s = Collections.synchronizedSortedSet(new TreeSet());
        SortedSet s2 = s.headSet(foo);
        //......此處省略部分程式碼
        synchronized (s) {  // Note: s, not s2!!!
            Iterator i = s2.iterator(); // Must be in the synchronized block
            while (i.hasNext())
                foo(i.next());
        }

不遵從此建議將導致無法確定的行為。如果指定的有序set是可序列化的,則返回的有序set也將是可序列化的

(47)static <T> Collection<T> unmodifiableCollection(Collection<? extends T> c):返回指定collection的不可修改檢視。此方法允許模組為使用者提供對內部collection的“只讀”訪問。在返回的collection上執行的查詢操作將“讀完”指定的collection。試圖修改返回的collection(不管是直接修改還是通過其迭代器進行修改)將導致丟擲UnsupportedOperationException。返回的collection不會將hashCode()和equals()操作傳遞給底層實現collection,但這依賴於Object的equals()和hashCode()方法。在底層實現collection是一個set或是一個列表的情況下,有必要遵守這些操作的協定。如果指定collection是可序列化的,則返回的collection也將是可序列化的

(48)static <T> List<T> unmodifiableList(List<? extends T> list):返回指定列表的不可修改檢視。此方法允許模組為使用者提供對內部列表的“只讀”訪問。在返回的列表上執行的查詢操作將“讀完”指定的列表。試圖修改返回的列表(不管是直接修改還是通過其迭代器進行修改)將導致丟擲UnsupportedOperationException。如果指定列表是可序列化的,則返回的列表也將是可序列化的。類似地,如果指定列表實現RandomAccess,則返回列表也將這樣做

(49)static <K, V> Map<K, V> unmodifiableMap(Map<? extends K, ? extends V> m):返回指定對映的不可修改檢視。此方法允許模組為使用者提供對內部對映的“只讀”訪問。在返回的對映上執行的查詢操作將“讀完”指定的對映。試圖修改返回的對映(不管是直接修改還是通過其collection檢視進行修改)將導致丟擲UnsupportedOperationException。如果指定對映是可序列化的,則返回的對映也將是可序列化的

(50)static <T> Set<T> unmodifiableSet(Set<? extends T> s):返回指定set的不可修改檢視。此方法允許模組為使用者提供對內部set的“只讀”訪問。在返回的set上執行的查詢操作將“讀完”指定的set。試圖修改返回的set(不管是直接修改還是通過其迭代器進行修改)將導致丟擲UnsupportedOperationException。如果指定set是可序列化的,則返回的set也將是可序列化的

(51)static <K, V> SortedMap<K, V> unmodifiableSortedMap(SortedMap<K, ? extends V> m):返回指定有序對映的不可修改檢視。此方法允許模組為使用者提供對內部有序對映的“只讀”訪問。在返回的有序對映上執行的查詢操作將“讀完”指定的有序對映。試圖修改返回的有序對映(無論是直接修改、通過其collection檢視修改,還是通過其subMap、headMap或tailMap檢視修改)將導致丟擲UnsupportedOperationException。如果指定的有序對映是可序列化的,則返回的有序對映也將是可序列化的

(52)static <T> SortedSet<T> unmodifiableSortedSet(SortedSet<T> s):返回指定有序set的不可修改檢視。此方法允許模組為使用者提供對內部有序set的“只讀”訪問。在返回的有序set上執行的查詢操作將“讀完”指定的有序set。試圖修改返回的有序set(無論是直接修改、通過其迭代器修改,還是通過其subSet、headSet或tailSet檢視修改)將導致丟擲UnsupportedOperationException。如果指定有序set是可序列化的,則返回的有序set也將是可序列化的

3、Collections.sort()方法的練習

        /**
         * 利用Collections.sort()方法對List<String>進行排序,要求:
         * (1)建立List<String>,向其中新增十個隨機字串
         * (2)每個字串的長度為10以內的隨機整數
         * (3)每個字串的每個字元都為隨機生成的字元,字元可以重複
         * (4)每個隨機字串不可重複
         */
        List<String> list = new ArrayList<String>();
        String str = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
        int strLength = str.length();
        Random random = new Random();

        for (int i = 0; i < 10; i++) {
            String s = "";

            do {
                //長度為 [1, 10]
                int len = random.nextInt(10) + 1;
                StringBuffer sb = new StringBuffer();
                for (int j = 0; j < len; j++) {
                    int index = random.nextInt(strLength);
                    sb.append(str.charAt(index));
                }
                s = sb.toString();
            } while (list.contains(s)); //list.contains(sb); 始終為false,必須使用list.contains(sb.toString());

            list.add(s);
        }

        System.out.println(list);
        Collections.sort(list);
        System.out.println(list);